電通総研のブログ - TECH PLAY

TECH PLAY

電通総研

電通総研 の技術ブログ

856

こんにちは、コミュニケーションIT事業部の瀧川です。 本記事は 電通国際情報サービス Advent Calendar 2023 の12/13(水)の投稿です。 同期の石田と チームきなこ としてISUCON13に参加しました。(初参加) https://isucon.net/archives/58001272.html 競技終盤でアプリケーションを壊してしまい、 記録なし という悔しい結果に終わってしまいました。(T_T) きなこさん(石田の愛犬)、名前を借りておきながらかたじけない。。 ISUCONとは 事前準備 当日の流れ 9:00-10:00 10:00-12:00 12:00-17:00 17:00-18:00 感想 ISUCONとは ISUCONはWebアプリのパフォーマンスチューニングのコンテストです。 年によって差異があるかもしれませんが、おおよそこんな感じかと思います。 当日チューニング対象のサーバーが複数台提供される。 アプリは複数言語で実装が用意されているため選択可能。(今年はGo, Perl , PHP , Python , Ruby , Rust, Node.js) 当日提供される、性能計測ツール(ベンチマーカー)を実行し、性能値 (スコア)を採点する。 競技時間中に記録された最後のスコアで順位を競う。 今年のお題は ISUPipe という動画配信サービスでした。 https://www.youtube.com/watch?v=OOyInZbM85k 事前準備 休日に何度か集まって準備しました。 過去問は数年分解きました。 初期セットアップ、デプロイ、ログ集計についてはなるべく自動化できるよう シェルスクリプト を用意しました。 https://github.com/Akihiro1001/isucon 集計シェルを実行すると GitHub issueにNginxの アクセスログ と MySQL のスロークエリの集計結果が出力されます。 また、ChatGPTと GitHub Copilotに課金して、前日は早く寝ました。💤 当日の流れ 9:00-10:00 平日よりも早起きをして、恵比寿駅に待ち合わせ。 コンビニでランチを買い、予約しておいた レンタルオフィス に無事到着。 作業環境を整え、眠気覚ましのコーヒーを大量に用意。 10:00-12:00 競技が開始し、まずは予定通りの分担で作業しました。 瀧川 事前に用意した各種 シェルスクリプト の微調整と各サーバーへの配置 アプリケーションのソースや ミドルウェア の設定ファイルを GitHub 管理 各種集計ツール(pt-query-digest, alp)のインストール Nginx, MySQL のログ設定やパラメータ調整 デプロイ → 計測 → 集計 の一連の処理を流す 石田 マニュアルの読み込みとアプリケーションの仕様把握 ソースコード の読み込みと ボトルネック になりそうな箇所の洗い出し 構成としては、以下がオールインワンになったサーバーが3台配られました。 DNS : PowerDNS + MySQL アプリ : Nginx + Go + MySQL Nginxと MySQL はヤマが的中して助かりました。 Apache と PostgreSQL だったら 心が折れる ところでした。 特徴的だったのは、 DNS もチューニング対象だったことです。 12:00-17:00 ボトルネック が見えてきたのでチューニングに着手。 以下の改善を入れました。 インデックスの追加 N+1の改善 キャッシュできそうな箇所はオンメモリにキャッシュ インサートをループしている箇所をバルクインサートに変更 PREPARED STATEMENTを無効化 アプリケーションのDBを別サーバーに移行 20位くらいに躍り出る瞬間もあり、盛り上がりました。😆 17:00-18:00 改善が進むと、 DNS への水責め攻撃が激しくなり、 ボトルネック がアプリから DNS へと移りました。 DNS レコードの TTL やcache- ttl が0に設定されていたため、設定を変更しキャッシュを有効化しました。 ですが、水責め攻撃にはそれほど効果が見られず。。 とりあえず DNS を別サーバーに移行して負荷分散しようとしたあたりで DNS 機能がクラッシュ😱 最後まで DNS を復旧できず、 記録なし に終わってしまいました。。 感想 来年に向けて反省点を残しておきます。 変更点は必ず残しておき、いつでも戻せるようにしておくべきでした。サーバーを直接いじる時は、とりあえず git init しておくのが良さそうです。 今回利用したGo言語は、普段業務で触っていないため、時間を作って慣れておくべきでした。 集計シェルはベンチマーカーが完了するのを待ってから手動で実行していました。今考えると、/initializeのエンドポイントでキックして、一定時間スリープ後に自動で集計するようにすれば手間を減らせました。 悔しい結果となってしまいましたが、とても良い経験になりました。 爆速なWebアプリを開発できるよう今後も精進します💪 一緒に参加した石田が明日の アドベントカレンダー を担当します。 執筆: @takigawa.akihiro 、レビュー: 寺山 輝 (@terayama.akira) ( Shodo で執筆されました )
こんにちは、コミュニケーションIT事業部の瀧川です。 本記事は 電通国際情報サービス Advent Calendar 2023 の12/13(水)の投稿です。 同期の石田と チームきなこ としてISUCON13に参加しました。(初参加) https://isucon.net/archives/58001272.html 競技終盤でアプリケーションを壊してしまい、 記録なし という悔しい結果に終わってしまいました。(T_T) きなこさん(石田の愛犬)、名前を借りておきながらかたじけない。。 ISUCONとは 事前準備 当日の流れ 9:00-10:00 10:00-12:00 12:00-17:00 17:00-18:00 感想 ISUCONとは ISUCONはWebアプリのパフォーマンスチューニングのコンテストです。 年によって差異があるかもしれませんが、おおよそこんな感じかと思います。 当日チューニング対象のサーバーが複数台提供される。 アプリは複数言語で実装が用意されているため選択可能。(今年はGo, Perl , PHP , Python , Ruby , Rust, Node.js) 当日提供される、性能計測ツール(ベンチマーカー)を実行し、性能値 (スコア)を採点する。 競技時間中に記録された最後のスコアで順位を競う。 今年のお題は ISUPipe という動画配信サービスでした。 https://www.youtube.com/watch?v=OOyInZbM85k 事前準備 休日に何度か集まって準備しました。 過去問は数年分解きました。 初期セットアップ、デプロイ、ログ集計についてはなるべく自動化できるよう シェルスクリプト を用意しました。 https://github.com/Akihiro1001/isucon 集計シェルを実行すると GitHub issueにNginxの アクセスログ と MySQL のスロークエリの集計結果が出力されます。 また、ChatGPTと GitHub Copilotに課金して、前日は早く寝ました。💤 当日の流れ 9:00-10:00 平日よりも早起きをして、恵比寿駅に待ち合わせ。 コンビニでランチを買い、予約しておいた レンタルオフィス に無事到着。 作業環境を整え、眠気覚ましのコーヒーを大量に用意。 10:00-12:00 競技が開始し、まずは予定通りの分担で作業しました。 瀧川 事前に用意した各種 シェルスクリプト の微調整と各サーバーへの配置 アプリケーションのソースや ミドルウェア の設定ファイルを GitHub 管理 各種集計ツール(pt-query-digest, alp)のインストール Nginx, MySQL のログ設定やパラメータ調整 デプロイ → 計測 → 集計 の一連の処理を流す 石田 マニュアルの読み込みとアプリケーションの仕様把握 ソースコード の読み込みと ボトルネック になりそうな箇所の洗い出し 構成としては、以下がオールインワンになったサーバーが3台配られました。 DNS : PowerDNS + MySQL アプリ : Nginx + Go + MySQL Nginxと MySQL はヤマが的中して助かりました。 Apache と PostgreSQL だったら 心が折れる ところでした。 特徴的だったのは、 DNS もチューニング対象だったことです。 12:00-17:00 ボトルネック が見えてきたのでチューニングに着手。 以下の改善を入れました。 インデックスの追加 N+1の改善 キャッシュできそうな箇所はオンメモリにキャッシュ インサートをループしている箇所をバルクインサートに変更 PREPARED STATEMENTを無効化 アプリケーションのDBを別サーバーに移行 20位くらいに躍り出る瞬間もあり、盛り上がりました。😆 17:00-18:00 改善が進むと、 DNS への水責め攻撃が激しくなり、 ボトルネック がアプリから DNS へと移りました。 DNS レコードの TTL やcache- ttl が0に設定されていたため、設定を変更しキャッシュを有効化しました。 ですが、水責め攻撃にはそれほど効果が見られず。。 とりあえず DNS を別サーバーに移行して負荷分散しようとしたあたりで DNS 機能がクラッシュ😱 最後まで DNS を復旧できず、 記録なし に終わってしまいました。。 感想 来年に向けて反省点を残しておきます。 変更点は必ず残しておき、いつでも戻せるようにしておくべきでした。サーバーを直接いじる時は、とりあえず git init しておくのが良さそうです。 今回利用したGo言語は、普段業務で触っていないため、時間を作って慣れておくべきでした。 集計シェルはベンチマーカーが完了するのを待ってから手動で実行していました。今考えると、/initializeのエンドポイントでキックして、一定時間スリープ後に自動で集計するようにすれば手間を減らせました。 悔しい結果となってしまいましたが、とても良い経験になりました。 爆速なWebアプリを開発できるよう今後も精進します💪 一緒に参加した石田が明日の アドベントカレンダー を担当します。 執筆: @takigawa.akihiro 、レビュー: 寺山 輝 (@terayama.akira) ( Shodo で執筆されました )
こんにちは。X(クロス) イノベーション 本部ソフトウェアデザインセンターの徳山です。 本記事は 電通国際情報サービス Advent Calendar 2023 の12月12日の記事となります。 ちなみに12月12日は「いい字一字」の語呂合わせで「 漢字の日 」だそうです。へぇ〜! 本記事はタイトルにありますFlutterFlowというノーコードツールを使用した記事となります。ノーコード・ローコードツールの業務利用に対してまだまだ懐疑的な開発者の方も多いと思いますが、FlutterFlowを実際に利用することで見えてきたことを本記事を通してご紹介できればと思います。 この記事を読むと何がわかるのか FlutterFlowとは何か 今回は何を行うのか 実際に作ってみる 前提条件 大まかな時間配分 成果物 作成の過程 初期設定 認証機能を実装 記録関連のページと機能を実装 カスタムファンクションの実装例 クエリーのフィルター設定例 マイページ関連のページと機能を実装 その他UI調整 評価 良い点 辛い点 まとめ この記事を読むと何がわかるのか FlutterFlowとは何か FlutterFlowの良い点、イマイチな点 FlutterFlowの使いどころ FlutterFlowとは何か FlutterFlowとは、 クロスプラットフォーム 開発に特化したノーコードツールとなります。FlutterFlowだけで iOS 、 Android 、Webでの開発に一度に対応できるというものです。多くのUI コンポーネント (FlutterFlowでは ウィジェット )が用意されており、ホバーなどのアクションやバリデーション、特定の条件下での表示・非表示の制御など全て GUI で設定を行うことができます。 また、有料機能となりますがコードのエクスポート機能を備えているため、途中からコードベースの開発に切り替えることも可能です。 今回は何を行うのか FlutterFlowの利用可能性についてご紹介するため簡単なデモアプリを作成してみたいと思います。 ただし、普通に作っても面白くないため今回はあえて5時間という時間制限を設けます。 ノーコード・ローコードツールを使うケースを想定するとあまり時間をかけずにサクッとアプリを作りたい場合が多いと思いますので、実例を示す点において良い制限ではないでしょうか。 実際に作ってみる 今回は「日々の筋トレを記録するアプリ」を作っていきます。 本アプリは下記の機能を持つアプリとなっています。 ト レーニン グ内容の記録と確認を行うことができる 「日付、種目、重量・回数・セット数、コメント」を記録 本日と過去の2種類の内容を確認 認証機能を利用できる アカウント作成、ログイン、ログアウト プロフィールの作成、変更ができる プロフィール画像 、アカウント名、メールアドレス 作る際のスタート地点を明確にするため前提としていくつか条件を設定しておきます。 前提条件 プロジェクトテンプレートは使用しない ページテンプレートやAI機能、Flows機能* の利用は可能 バックエンドやデータベースは連携可能なFirebaseサービスを利用 Flows:複数のページや コンポーネント にまたがる機能セットのテンプレート 大まかな時間配分 初期設定(Firebaseとの連携):30分 大枠のUI作成:2時間半 機能実装:2時間半 成果物 実際に作ったアプリのストーリーボードは下記となります。 時間の制約上かなり簡素なアプリですが、最低限のログイン、ログアウト機能や CRUD 機能を実装することができました。 作成の過程 では、どのようにアプリを作成したのか順を追って説明します。 初期設定 まずはアプリケーションの初期設定を行います。 新規作成時にアプリケーションの配色やFirebaseとのセットアップを行うことができます。これらはもちろん後から変更することもできます。 次のステップでは実際にFlutterFlowからFirebaseでのプロジェクトが作成できます。 どのように設定や連携すれば良いか不安、という場合でもプロジェクト作成後の設定画面ではドキュメントや チュートリアル 動画へのリンクが用意されています。英語ですが、どの設定のページにも用意されているので随時参照しながらアプリの作成を進めることができます。 ドキュメントや チュートリアル に従い下記の3つのセットアップを終わらせます。 認証:Firebase Authentication データベース:Firestore Database ストレージ:Firebase Storage 認証機能を実装 まずはUIを実装します。便利なことにFlutterFlowでは Flows と呼ばれる機能が最近実装されました。 これはよく使われる一連の機能とページをまとめてプロジェクトで利用できるものです。 例えばアカウント作成、ログイン、パスワードリセットの機能とページを丸ごとテンプレートとして利用できます。 個別で作成するとUI作成とページの遷移の連携、フォーカス時のアクションなど時間がかかる作業もあっという間に実装できてしまいます。 今回はアカウント作成周りの機能とページで利用します。 FlutterFlowは GUI ツールのため、用意された豊富な ウィジェット (UI コンポーネント のこと)を ドラッグ&ドロップ で配置できます。ページの構成は Figma ようなツリー構造で表示されます。 構造上配置できない箇所へのドロップやプロパティの変更時には変更は破棄されエラーが表示されるようになっています。 それぞれの ウィジェット には アクション を設定できます。 例えば、「プロフィールを変更する」ボタンを押したら下記のアクションを個別に組み合わせて設定できます。 ①フォームのバリデーションを実施 ②パスしたらFirebaseで用意したusersコレクションにデータを保存 ③指定したページに遷移 ④スナックバーを表示 認証のFlowsにはアクションも自動的に設定されていたため、アクションに関してはログイン後のページだけ指定を行うだけで済みました。 記録関連のページと機能を実装 できるだけページ数を減らすために記録関連の新規作成、編集、削除はモーダルで行うようにします。 ワークアウト用のコレクションも必要になりますが、FlutterFlow上で簡単に登録できます。 アクション同様、コレクションへのクエリ操作もページの ウィジェット 選択時に選択できます。 フォームバリデーションやエラーメッセージの表示もform ウィジェット からフィールドごとに簡単に行うことができます。 また、記録の一覧取得もworkoutコレクションへのクエリーを設定することで実装します。 FlutterFlowには特定の日付を指定して該当するデータだけを取得する機能、例えば12月12日に記録したト レーニン グのデータだけを抜き出すといった機能は提供されていません。その代わり、指定した値との大小を比較してフィルターする条件をクエリーに付与できます。そのため、記録日の開始時刻(0時0分0秒)と翌日の開始時刻を取得する関数を独自に作成し、記録日時の値と比較することで一覧を取得するようにします。 FlutterFlowで提供されていない独自の関数を利用する場合、 カスタムファンクション という機能を利用できます。 Dart 言語に関する知識が必要になり実装経験はありませんでしたが、ChatGPTを利用して実装を行いました。 以下は「本日と次の日の開始時刻」を取得してDateTime型で返却する独自関数の実装例とクエリーの設定例です。 カスタムファンクションの実装例 DateTime ? getTodayStartTime () { /// MODIFY CODE ONLY BELOW THIS LINE DateTime now = DateTime . now (); DateTime todayStartTime = DateTime (now.year, now.month, now.day); return todayStartTime; /// MODIFY CODE ONLY ABOVE THIS LINE } DateTime ? getTomorrowStartTime () { /// MODIFY CODE ONLY BELOW THIS LINE DateTime now = DateTime . now (); DateTime tomorrowStartTime = DateTime (now.year, now.month, now.day + 1 ); return tomorrowStartTime; /// MODIFY CODE ONLY ABOVE THIS LINE } クエリーのフィルター設定例 filter条件を3つ指定しています。 記録日時が記録日翌日の0時0分0秒より前 記録日時が記録日当日の0時0分0秒より後 ログインユーザー本人が作成した記録 以上のようにフィルター条件を組み合わせることで当日と昨日以前の記録一覧をそれぞれ取得することができるようになりました。 マイページ関連のページと機能を実装 行うことは記録関連と同じため特に真新しいことはありません。 ログアウト時にダイアログを表示し、押されたボタンに応じたアクションを設定しています。 その他UI調整 ページ下部と上部に表示するナビゲーションバーとアプリケーションバーの設定を行います。 どちらも画面上から簡単に設定できます。 評価 実際にアプリケーションを作ってみることで、FlutterFlowの良し悪しが見えてきましたのでまとめてました。 良い点 アップデートサイクルが早い 毎月のように リリースノート が更新されており、新規機能のアップデートや改善が行われているためプロダクトしての力の入れ具合を感じます。 見やすく操作性の良いUI ノーコード関連のツールは多くありますが、UIとして圧迫感を感じず操作性も良いため設定項目の多いツールとして使いやすいと感じました。 FlutterFlowにはAI機能も組み込まれており、テンプレート機能と組み合わせることで部分的にですが高速に モックアップ を作成することができました。 ドキュメントが豊富・親切 英語のみですが、ドキュメント量が豊富で動画付きの箇所も多いためため操作で困ってしまった箇所はほとんどありませんでした。 コードベースの開発に切り替えられる柔軟性 有料機能ですが、FlutterFlowで開発したアプリケーションはFlutterとしてexportすることができ、 Dart での開発に切り替えることができます。そのため、初期段階はFlutterFlowで開発し、手の込んだ開発や開発人数が増えてきた段階でコードベースの開発に切り替えるといったことができます。 コードエクスポートに対応したノーコードツールはあまりないため、開発体制を柔軟に切り替えられ点は良いと感じました。 辛い点 開発体験として惜しい点が多い 確認時のテストモードの立ち上げやリロードに時間がかかります。立ち上げは数分程度、変更を反映する際のリロードには10秒程度かかります。 また、セッションも10分程度しか維持されないため作業に集中していると頻繁に立ち上げ直しすることになりました。 GUI ツールの性質上仕方がないですがショートカットが少ないためマウスでの操作が中心となります。普段 VS Code でショートカットを多用する身としては最初のうちはフラストレーションが溜まりました。 共同編集や複雑な操作には向かない プランをアップグレードすることで共同作業ができます。ただし、同じファイルを同時にといった スプレッドシート のようなことはできないため複数人での共同編集には向かない印象です。 また、UIやアニメーションといった見た目に関する機能は柔軟かつ豊富ですが、バックエンドと連携する機能面では少し物足りない印象です。例えばフォーム送信時に複数のコレクションにデータを作成するといったアクション設定ができない、日時を絞り込んだデータを取得できないといったことが今回のアプリ作成時にわかりました。 利用シーンによっては Dart やFlutterFlowのキャッチアップハードルが高い FlutterFlowはできることが多い一方で、何ができるのかを把握することが大変です。英語ということもあり機能の解釈が間違っていたり該当するドキュメントをうまく見つけることができないといったことがよくありました。 また、中規模以上の システム開発 での利用となるとカスタムファンクションの利用やコードベースの開発が必要になることが予想されます。そうした場合に Dart などのモバイルアプリ向け言語の利用経験がないとキャッチアップに時間を要するためハードルとしては高くなってしまうのではないかと感じました。 まとめ ノーコードツールの利用経験がなかったこともあり使い勝手がわからず利用シーンも今までイメージがつきませんでした。今回実際に使ってみることで、モバイルアプリケーションにおけるMVP(Minimum Viable Product)や モックアップ の作成といった用途において利用できるのではないかと感じました。 システム開発 において中心的存在となるものではないかもしれませんが、既存の開発手法と合わせて価値を発揮できる可能性はあると思いますので皆さんもお時間があればぜひ触ってみてください。 私たちは一緒に働いてくれる仲間を募集しています! フルサイクルエンジニア 執筆: @tokuyama 、レビュー: @nakamura.toshihiro ( Shodo で執筆されました )
こんにちは。X(クロス) イノベーション 本部ソフトウェアデザインセンターの徳山です。 本記事は 電通国際情報サービス Advent Calendar 2023 の12月12日の記事となります。 ちなみに12月12日は「いい字一字」の語呂合わせで「 漢字の日 」だそうです。へぇ〜! 本記事はタイトルにありますFlutterFlowというノーコードツールを使用した記事となります。ノーコード・ローコードツールの業務利用に対してまだまだ懐疑的な開発者の方も多いと思いますが、FlutterFlowを実際に利用することで見えてきたことを本記事を通してご紹介できればと思います。 また、FlutterFlowに関連した記事を新たに追加しましたのでFlutterFlowやFirebaseについてより深く知りたい方はぜひ覗いてみてください。 FlutterFlowとは?ノーコードでスマホアプリ開発を始める方法 - 電通総研 テックブログ FlutterFlow vs Adalo:ノーコードモバイルアプリ開発ツールの比較 - 電通総研 テックブログ FlutterFlowに制約はある?できることとできないこと - 電通総研 テックブログ FlutterFlowでFirebaseと連携する方法 - 電通総研 テックブログ FlutterFlowでサクっと開発する社内業務スマホアプリ - 電通総研 テックブログ この記事を読むと何がわかるのか FlutterFlowとは何か 今回は何を行うのか 実際に作ってみる 前提条件 大まかな時間配分 成果物 作成の過程 初期設定 認証機能を実装 記録関連のページと機能を実装 カスタムファンクションの実装例 クエリーのフィルター設定例 マイページ関連のページと機能を実装 その他UI調整 評価 良い点 辛い点 まとめ この記事を読むと何がわかるのか FlutterFlowとは何か FlutterFlowの良い点、イマイチな点 FlutterFlowの使いどころ FlutterFlowとは何か FlutterFlowとは、 クロスプラットフォーム 開発に特化したノーコードツールとなります。FlutterFlowだけで iOS 、 Android 、Webでの開発に一度に対応できるというものです。多くのUI コンポーネント (FlutterFlowでは ウィジェット )が用意されており、ホバーなどのアクションやバリデーション、特定の条件下での表示・非表示の制御など全て GUI で設定を行うことができます。 また、有料機能となりますがコードのエクスポート機能を備えているため、途中からコードベースの開発に切り替えることも可能です。 今回は何を行うのか FlutterFlowの利用可能性についてご紹介するため簡単なデモアプリを作成してみたいと思います。 ただし、普通に作っても面白くないため今回はあえて5時間という時間制限を設けます。 ノーコード・ローコードツールを使うケースを想定するとあまり時間をかけずにサクッとアプリを作りたい場合が多いと思いますので、実例を示す点において良い制限ではないでしょうか。 実際に作ってみる 今回は「日々の筋トレを記録するアプリ」を作っていきます。 本アプリは下記の機能を持つアプリとなっています。 ト レーニン グ内容の記録と確認を行うことができる 「日付、種目、重量・回数・セット数、コメント」を記録 本日と過去の2種類の内容を確認 認証機能を利用できる アカウント作成、ログイン、ログアウト プロフィールの作成、変更ができる プロフィール画像 、アカウント名、メールアドレス 作る際のスタート地点を明確にするため前提としていくつか条件を設定しておきます。 前提条件 プロジェクトテンプレートは使用しない ページテンプレートやAI機能、Flows機能* の利用は可能 バックエンドやデータベースは連携可能なFirebaseサービスを利用 Flows:複数のページや コンポーネント にまたがる機能セットのテンプレート 大まかな時間配分 初期設定(Firebaseとの連携):30分 大枠のUI作成:2時間半 機能実装:2時間半 成果物 実際に作ったアプリのストーリーボードは下記となります。 時間の制約上かなり簡素なアプリですが、最低限のログイン、ログアウト機能や CRUD 機能を実装することができました。 作成の過程 では、どのようにアプリを作成したのか順を追って説明します。 初期設定 まずはアプリケーションの初期設定を行います。 新規作成時にアプリケーションの配色やFirebaseとのセットアップを行うことができます。これらはもちろん後から変更することもできます。 次のステップでは実際にFlutterFlowからFirebaseでのプロジェクトが作成できます。 どのように設定や連携すれば良いか不安、という場合でもプロジェクト作成後の設定画面ではドキュメントや チュートリアル 動画へのリンクが用意されています。英語ですが、どの設定のページにも用意されているので随時参照しながらアプリの作成を進めることができます。 ドキュメントや チュートリアル に従い下記の3つのセットアップを終わらせます。 認証:Firebase Authentication データベース:Firestore Database ストレージ:Firebase Storage 認証機能を実装 まずはUIを実装します。便利なことにFlutterFlowでは Flows と呼ばれる機能が最近実装されました。 これはよく使われる一連の機能とページをまとめてプロジェクトで利用できるものです。 例えばアカウント作成、ログイン、パスワードリセットの機能とページを丸ごとテンプレートとして利用できます。 個別で作成するとUI作成とページの遷移の連携、フォーカス時のアクションなど時間がかかる作業もあっという間に実装できてしまいます。 今回はアカウント作成周りの機能とページで利用します。 FlutterFlowは GUI ツールのため、用意された豊富な ウィジェット (UI コンポーネント のこと)を ドラッグ&ドロップ で配置できます。ページの構成は Figma ようなツリー構造で表示されます。 構造上配置できない箇所へのドロップやプロパティの変更時には変更は破棄されエラーが表示されるようになっています。 それぞれの ウィジェット には アクション を設定できます。 例えば、「プロフィールを変更する」ボタンを押したら下記のアクションを個別に組み合わせて設定できます。 ①フォームのバリデーションを実施 ②パスしたらFirebaseで用意したusersコレクションにデータを保存 ③指定したページに遷移 ④スナックバーを表示 認証のFlowsにはアクションも自動的に設定されていたため、アクションに関してはログイン後のページだけ指定を行うだけで済みました。 記録関連のページと機能を実装 できるだけページ数を減らすために記録関連の新規作成、編集、削除はモーダルで行うようにします。 ワークアウト用のコレクションも必要になりますが、FlutterFlow上で簡単に登録できます。 アクション同様、コレクションへのクエリ操作もページの ウィジェット 選択時に選択できます。 フォームバリデーションやエラーメッセージの表示もform ウィジェット からフィールドごとに簡単に行うことができます。 また、記録の一覧取得もworkoutコレクションへのクエリーを設定することで実装します。 FlutterFlowには特定の日付を指定して該当するデータだけを取得する機能、例えば12月12日に記録したト レーニン グのデータだけを抜き出すといった機能は提供されていません。その代わり、指定した値との大小を比較してフィルターする条件をクエリーに付与できます。そのため、記録日の開始時刻(0時0分0秒)と翌日の開始時刻を取得する関数を独自に作成し、記録日時の値と比較することで一覧を取得するようにします。 FlutterFlowで提供されていない独自の関数を利用する場合、 カスタムファンクション という機能を利用できます。 Dart 言語に関する知識が必要になり実装経験はありませんでしたが、ChatGPTを利用して実装を行いました。 以下は「本日と次の日の開始時刻」を取得してDateTime型で返却する独自関数の実装例とクエリーの設定例です。 カスタムファンクションの実装例 DateTime? getTodayStartTime() { /// MODIFY CODE ONLY BELOW THIS LINE DateTime now = DateTime.now(); DateTime todayStartTime = DateTime(now.year, now.month, now.day); return todayStartTime; /// MODIFY CODE ONLY ABOVE THIS LINE } DateTime? getTomorrowStartTime() { /// MODIFY CODE ONLY BELOW THIS LINE DateTime now = DateTime.now(); DateTime tomorrowStartTime = DateTime(now.year, now.month, now.day + 1); return tomorrowStartTime; /// MODIFY CODE ONLY ABOVE THIS LINE } クエリーのフィルター設定例 filter条件を3つ指定しています。 記録日時が記録日翌日の0時0分0秒より前 記録日時が記録日当日の0時0分0秒より後 ログインユーザー本人が作成した記録 以上のようにフィルター条件を組み合わせることで当日と昨日以前の記録一覧をそれぞれ取得することができるようになりました。 マイページ関連のページと機能を実装 行うことは記録関連と同じため特に真新しいことはありません。 ログアウト時にダイアログを表示し、押されたボタンに応じたアクションを設定しています。 その他UI調整 ページ下部と上部に表示するナビゲーションバーとアプリケーションバーの設定を行います。 どちらも画面上から簡単に設定できます。 評価 実際にアプリケーションを作ってみることで、FlutterFlowの良し悪しが見えてきましたのでまとめてました。 良い点 アップデートサイクルが早い 毎月のように リリースノート が更新されており、新規機能のアップデートや改善が行われているためプロダクトしての力の入れ具合を感じます。 見やすく操作性の良いUI ノーコード関連のツールは多くありますが、UIとして圧迫感を感じず操作性も良いため設定項目の多いツールとして使いやすいと感じました。 FlutterFlowにはAI機能も組み込まれており、テンプレート機能と組み合わせることで部分的にですが高速に モックアップ を作成することができました。 ドキュメントが豊富・親切 英語のみですが、ドキュメント量が豊富で動画付きの箇所も多いためため操作で困ってしまった箇所はほとんどありませんでした。 コードベースの開発に切り替えられる柔軟性 有料機能ですが、FlutterFlowで開発したアプリケーションはFlutterとしてexportすることができ、 Dart での開発に切り替えることができます。そのため、初期段階はFlutterFlowで開発し、手の込んだ開発や開発人数が増えてきた段階でコードベースの開発に切り替えるといったことができます。 コードエクスポートに対応したノーコードツールはあまりないため、開発体制を柔軟に切り替えられ点は良いと感じました。 辛い点 開発体験として惜しい点が多い 確認時のテストモードの立ち上げやリロードに時間がかかります。立ち上げは数分程度、変更を反映する際のリロードには10秒程度かかります。 また、セッションも10分程度しか維持されないため作業に集中していると頻繁に立ち上げ直しすることになりました。 GUI ツールの性質上仕方がないですがショートカットが少ないためマウスでの操作が中心となります。普段 VS Code でショートカットを多用する身としては最初のうちはフラストレーションが溜まりました。 共同編集や複雑な操作には向かない プランをアップグレードすることで共同作業ができます。ただし、同じファイルを同時にといった スプレッドシート のようなことはできないため複数人での共同編集には向かない印象です。 また、UIやアニメーションといった見た目に関する機能は柔軟かつ豊富ですが、バックエンドと連携する機能面では少し物足りない印象です。例えばフォーム送信時に複数のコレクションにデータを作成するといったアクション設定ができない、日時を絞り込んだデータを取得できないといったことが今回のアプリ作成時にわかりました。 利用シーンによっては Dart やFlutterFlowのキャッチアップハードルが高い FlutterFlowはできることが多い一方で、何ができるのかを把握することが大変です。英語ということもあり機能の解釈が間違っていたり該当するドキュメントをうまく見つけることができないといったことがよくありました。 また、中規模以上の システム開発 での利用となるとカスタムファンクションの利用やコードベースの開発が必要になることが予想されます。そうした場合に Dart などのモバイルアプリ向け言語の利用経験がないとキャッチアップに時間を要するためハードルとしては高くなってしまうのではないかと感じました。 まとめ ノーコードツールの利用経験がなかったこともあり使い勝手がわからず利用シーンも今までイメージがつきませんでした。今回実際に使ってみることで、モバイルアプリケーションにおけるMVP(Minimum Viable Product)や モックアップ の作成といった用途において利用できるのではないかと感じました。 システム開発 において中心的存在となるものではないかもしれませんが、既存の開発手法と合わせて価値を発揮できる可能性はあると思いますので皆さんもお時間があればぜひ触ってみてください。 私たちは一緒に働いてくれる仲間を募集しています! フルサイクルエンジニア 執筆: @tokuyama 、レビュー: @nakamura.toshihiro ( Shodo で執筆されました )
こんにちは、金融ソリューション事業部兼テックブログ編集部の若本です。 今回は、テックブログ編集部で取り組んでいる運営改善の取り組みの一部をご紹介します。 本記事は 電通国際情報サービス Advent Calendar 2023 の11日目の記事です。 テックブログ編集部について 運営上の課題 アプローチ レビュアーガチャの仕組み おわりに テックブログ編集部について ISIDにはテックブログ編集部というバーチャル組織があり、ISIDテックブログの企画や運営を行っています 。 テックブログ編集部の中身は 中村さんの記事 に詳しくまとまっていますので、ご興味のある方はこちらもぜひご一読ください。 編集部のうち、私は執筆管理チームに所属しています。執筆管理チームの役割は、一連のレビュープロセスを含めた記事の管理です。図にまとめると以下のようになります。 これらのタスクはチャットベースで執筆管理チーム内の認識を合わせつつ、2週に1度の定例で状況確認や改善のためのディスカッションを行っています。 運営上の課題 テックブログ編集部では、記事のレビューに関して以下のような課題がありました。 レビュアーがなかなかつかず、チャットでの調整が必要になる場合がある 特に実装系、ニッチな技術領域の記事は 心理的 にレビューしづらい状態にありました。 そもそも、記事のレビュー待ちメールに気が付いていない 執筆された記事はレビュー待ちの状態になりメールが飛びますが、業務メールの波に流されてしまいレビューされない記事が発生することがありました。 こういった問題は 長期的にみると執筆者離れを引き起こすため、テックブログ運営においては非常に重要な問題 です。 特にISID テックブログでは、記事の執筆は個々人のモチベーションに委ねるところが大きいため、執筆者のストレス増・モチベーション低下につながるプロセスは改善していく必要があります。 アプローチ 上記の課題に対して、テックブログ編集部では以下の対策を考えました。 レビュアーガチャ 技術の詳細な内容はともかく、 発信して問題ない内容や文章になっているかは編集部員がランダムで担当する のがいいのでは? 気づきにくいメールやレビュー管理画面ではなく、 メンションで通知を飛ばせるTeamsで通知する形にしたい 。 今回は、これらの仕組みをPower Autometeの クラウド フローを使って実現します。具体的には、「テックブログのレビュー依頼メール」が飛んできたときにTeamsのチャネル上でランダムにメンションするフローを作成します。 Power Autometeのフローについては 根本さんの記事 をご覧ください。 レビュアーガチャの仕組み 「テックブログのレビュー依頼メール」は以下のようなものです。ISID テックブログ編集部ではレビュー管理にShodoを採用しており、執筆完了の折にはメールが自動配信されます。 このとき、メール本文には「記事のタイトル/レビューリンク」が、メールの メタデータ には「差出人」が含まれています。 レビューに必要な情報はメールに含まれているため、メールの情報を解析して必要な情報のみ抽出します。 後は、 ガチャ要素として編集部員のメンバーから1人ランダムに割り当てます 。これは、編集部員のメンバーの一覧を取得して乱数で選択することで実現することができます。 仕組みは以下の通りです。 上記をPower Automate上でフローとして実装していきました(フロー全体のスクショは長すぎたため割愛します)。 発行すると、レビュー依頼メール受信時にランダムでメンションされるようになります。これにより、 レビュー担当予定者者が明確になり、レビュー割り当て時にはメンション付きで通知されるようになりました! おわりに 本記事では、テックブログ編集部の施策例としてレビュアーガチャが実現するまでの流れをご紹介しました。 今回は触れませんでしたが、上記のようないかにもテックブログらしい施策だけではなく、執筆マニュアルや相談窓口の設置などといったレビューフロー全体の整備を行っています。ISID テックブログでは、今後も執筆者の方がいきいきと執筆できる環境づくりを目指して取り組みを進めていきます。 執筆: @wakamoto.ryosuke 、レビュー: @yamashita.tsuyoshi ( Shodo で執筆されました )
こんにちは、金融ソリューション事業部兼テックブログ編集部の若本です。 今回は、テックブログ編集部で取り組んでいる運営改善の取り組みの一部をご紹介します。 本記事は 電通国際情報サービス Advent Calendar 2023 の11日目の記事です。 テックブログ編集部について 運営上の課題 アプローチ レビュアーガチャの仕組み おわりに テックブログ編集部について ISIDにはテックブログ編集部というバーチャル組織があり、ISIDテックブログの企画や運営を行っています 。 テックブログ編集部の中身は 中村さんの記事 に詳しくまとまっていますので、ご興味のある方はこちらもぜひご一読ください。 編集部のうち、私は執筆管理チームに所属しています。執筆管理チームの役割は、一連のレビュープロセスを含めた記事の管理です。図にまとめると以下のようになります。 これらのタスクはチャットベースで執筆管理チーム内の認識を合わせつつ、2週に1度の定例で状況確認や改善のためのディスカッションを行っています。 運営上の課題 テックブログ編集部では、記事のレビューに関して以下のような課題がありました。 レビュアーがなかなかつかず、チャットでの調整が必要になる場合がある 特に実装系、ニッチな技術領域の記事は 心理的 にレビューしづらい状態にありました。 そもそも、記事のレビュー待ちメールに気が付いていない 執筆された記事はレビュー待ちの状態になりメールが飛びますが、業務メールの波に流されてしまいレビューされない記事が発生することがありました。 こういった問題は 長期的にみると執筆者離れを引き起こすため、テックブログ運営においては非常に重要な問題 です。 特にISID テックブログでは、記事の執筆は個々人のモチベーションに委ねるところが大きいため、執筆者のストレス増・モチベーション低下につながるプロセスは改善していく必要があります。 アプローチ 上記の課題に対して、テックブログ編集部では以下の対策を考えました。 レビュアーガチャ 技術の詳細な内容はともかく、 発信して問題ない内容や文章になっているかは編集部員がランダムで担当する のがいいのでは? 気づきにくいメールやレビュー管理画面ではなく、 メンションで通知を飛ばせるTeamsで通知する形にしたい 。 今回は、これらの仕組みをPower Autometeの クラウド フローを使って実現します。具体的には、「テックブログのレビュー依頼メール」が飛んできたときにTeamsのチャネル上でランダムにメンションするフローを作成します。 Power Autometeのフローについては 根本さんの記事 をご覧ください。 レビュアーガチャの仕組み 「テックブログのレビュー依頼メール」は以下のようなものです。ISID テックブログ編集部ではレビュー管理にShodoを採用しており、執筆完了の折にはメールが自動配信されます。 このとき、メール本文には「記事のタイトル/レビューリンク」が、メールの メタデータ には「差出人」が含まれています。 レビューに必要な情報はメールに含まれているため、メールの情報を解析して必要な情報のみ抽出します。 後は、 ガチャ要素として編集部員のメンバーから1人ランダムに割り当てます 。これは、編集部員のメンバーの一覧を取得して乱数で選択することで実現することができます。 仕組みは以下の通りです。 上記をPower Automate上でフローとして実装していきました(フロー全体のスクショは長すぎたため割愛します)。 発行すると、レビュー依頼メール受信時にランダムでメンションされるようになります。これにより、 レビュー担当予定者者が明確になり、レビュー割り当て時にはメンション付きで通知されるようになりました! おわりに 本記事では、テックブログ編集部の施策例としてレビュアーガチャが実現するまでの流れをご紹介しました。 今回は触れませんでしたが、上記のようないかにもテックブログらしい施策だけではなく、執筆マニュアルや相談窓口の設置などといったレビューフロー全体の整備を行っています。ISID テックブログでは、今後も執筆者の方がいきいきと執筆できる環境づくりを目指して取り組みを進めていきます。 執筆: @wakamoto.ryosuke 、レビュー: @yamashita.tsuyoshi ( Shodo で執筆されました )
こんにちは、X イノベーション 本部ソフトウェアデザインセンターの中村です。 本記事は 電通国際情報サービス Advent Calendar 2023 の12月8日の記事です。 皆さんはデータベースアクセスを行うアプリケーションの ユニットテスト やインテグレーションテストをどのように実施していますか?絶対の正解はありませんが、テストの効率性や正確性などを考慮して様々な工夫や検討がなされる領域だと思います。例えば次のような戦略があります。 データベースアクセス部分をモックにする 運用時のデータベースよりも高速なインメモリデータベースを使う(例えば H2 Database Engine など) 開発者のローカル環境に運用環境と同等のテスト用データベースをインストールする 本記事では、 Testcontainers を使ってデータベースアクセスを伴うテストを効率的に実施する方法をコードを交えながら紹介します。 本記事で伝えたいこと 最初に、本記事で伝えたいことを簡単にまとめておきます。 TestContainersの API よりも JDBC の接続URLを使おう データベースはデーモンモードで起動しよう テスト同士が影響しないようにテスト毎に ロールバック を実行しよう Testcontainersとは? Testcontainersは、Dockerコンテナで実行できるデータベースなどのソフトウェアに関して軽量で使い捨て可能な インスタンス を提供するための オープンソース フレームワーク です。 この フレームワーク を使うと、運用環境と同等のデータベース インスタンス をテスト環境で何度でも簡単に再現し利用できます。 Testcontainersでは、 Java 、Go、.NET、Node.jsなど多数の プログラミング言語 がサポートされています。 前提 本記事の前提は以下のとおりです。 Testcontainers for Java を使う Dockerを動かす環境としてはDocker Desktopを使う プログラミング言語 にはKotlinを使う データベースには PostgreSQL を使う データベースアクセスの フレームワーク には Komapper を使う ビルドツールにはGradle Wrapperを使う(Gradleのバージョンは以下のとおり) ./gradlew -v ------------------------------------------------------------ Gradle 8.5 ------------------------------------------------------------ Build time: 2023-11-29 14:08:57 UTC Revision: 28aca86a7180baa17117e0e5ba01d8ea9feca598 Kotlin: 1.9.20 Groovy: 3.0.17 Ant: Apache Ant(TM) version 1.10.13 compiled on January 4 2023 JVM: 21.0.1 (Azul Systems, Inc. 21.0.1+12-LTS) OS: Mac OS X 12.6 x86_64 データベースアクセスの フレームワーク であるKomapperについて少し補足をします。Komapperは、 MySQL 、 PostgreSQL 、 Oracle Databaseなどの代表的なリレーショナルデータベースに対応した O/Rマッピング フレームワーク です。Kotlin製の代表的な O/Rマッピング フレームワーク である Exposed ほどの 知名度 はありませんが機能性や使いやすさでは負けていません(と、Komapperの作者である私は考えています😁)。Komapperでは様々なデータベースとの稼働確認をTestcontainersを用いて行っています。 本記事にはデータベース、 フレームワーク 、ビルドツールに強く依存した説明はありませんので適宜お好みの環境に置き換えてお読みいただけます。ただし、 プログラミング言語 については JVM 言語以外に読み替えるのは難しいかもしれません。 本記事で示すサンプルコードは Getting started with Testcontainers for Java を下敷きにしています。ぜひ見比べてみてください。 Gradleの設定 以下のようなbuild.gradle.ktsを用意します。 plugins { application id( "com.google.devtools.ksp" ) version "1.9.21-1.0.15" kotlin( "jvm" ) version "1.9.21" } group = "org.example" version = "1.0-SNAPSHOT" repositories { mavenCentral() } dependencies { // Komapperの設定 platform( "org.komapper:komapper-platform:1.15.0" ).let { implementation(it) ksp(it) } implementation( "org.komapper:komapper-starter-jdbc" ) implementation( "org.komapper:komapper-dialect-postgresql-jdbc" ) ksp( "org.komapper:komapper-processor" ) // Testcontainersの設定 testImplementation(platform( "org.testcontainers:testcontainers-bom:1.19.3" )) testRuntimeOnly( "org.testcontainers:postgresql" ) // JUnitの設定 testImplementation( "org.junit.jupiter:junit-jupiter-api:5.9.2" ) testRuntimeOnly( "org.junit.jupiter:junit-jupiter-engine:5.9.2" ) } tasks.getByName<Test>( "test" ) { useJUnitPlatform() // GradleのプロパティをJavaのシステムプロパティに引き継ぐ val jdbcUrl = project.property( "jdbc.url" ) ?: error( "jdbc.url not found" ) systemProperty( "jdbc.url" , jdbcUrl) } ポイントは以下のとおりです。 利用するライブラリ(Kotlin、Komapper、Testcontainers、 JUnit )への依存を示す JDBC の接続URLをGradleのプロパティを介してアプリケーションに渡す ビジネスロジック データベース上の customers テーブルに対応する Customer エンティティクラスを定義します。 package example import org.komapper. annotation .KomapperEntity import org.komapper. annotation .KomapperId import org.komapper. annotation .KomapperTable @KomapperEntity @KomapperTable ( "customers" ) data class Customer( @KomapperId val id: Long , val name: String ) Komapperが認識できるようにKomapperの アノテーション を付与しています。 Customer エンティティクラスを使ってデータの追加や取得を行うサービスクラスは次のようになります。 package example import org.komapper.core.dsl.Meta import org.komapper.core.dsl.QueryDsl import org.komapper.jdbc.JdbcDatabase class CustomerService( private val db: JdbcDatabase) { // Customerエンティティクラスのメタモデル private val c = Meta.customer fun createCustomer(customer: Customer) { db.runQuery { // 対応するSQL: insert into customers (id, name) values (?, ?) QueryDsl.insert(c).single(customer) } } fun getAllCustomers(): List <Customer> { return db.runQuery { // 対応するSQL: select t0_.id, t0_.name from customers as t0_ QueryDsl.from(c) } } } データの追加や取得にはKomapperの API を使います。 API から発行する SQL はコード内のコメントに示したとおりです。 テストコード Getting started with Testcontainers for Java では、テストを制御するコードとテストコードが同じクラスに記述されていますが、本記事では分離して示します。 テストを制御するためのコード テストを制御するコードは以下のようになります。このコードは一度書けば複数のテストクラスから再利用できます。 package example import org.junit.jupiter.api.extension.AfterTestExecutionCallback import org.junit.jupiter.api.extension.BeforeAllCallback import org.junit.jupiter.api.extension.BeforeTestExecutionCallback import org.junit.jupiter.api.extension.ExtensionContext import org.junit.jupiter.api.extension.ParameterContext import org.junit.jupiter.api.extension.ParameterResolver import org.komapper.core.dsl.Meta import org.komapper.core.dsl.QueryDsl import org.komapper.jdbc.JdbcDatabase import org.komapper.tx.core.TransactionProperty import org.komapper.tx.jdbc.JdbcTransactionSession class DatabaseTestSupport : BeforeAllCallback, BeforeTestExecutionCallback, AfterTestExecutionCallback, ParameterResolver { companion object { @Volatile private var initialized: Boolean = false // Komapperのデータベース private val db = JdbcDatabase(url = System.getProperty( "jdbc.url" ) ?: error( "jdbc.url not found" )) // Komapperのトランザクションマネージャー private val transactionManager = run { val session = db.config.session as JdbcTransactionSession session.transactionManager } } // 最初のテストを実行する前に一度だけ cusotmers テーブルを作成する override fun beforeAll(context: ExtensionContext) { if ( ! initialized) { initialized = true db.runQuery { // 対応するSQL: create table if not exists customers (id bigint not null, name text not null, constraint pk_customers primary key(id)) QueryDsl.create(Meta.customer) } } } // テストメソッドの実行前にトランザクションを開始する override fun beforeTestExecution(context: ExtensionContext) { transactionManager.begin(TransactionProperty.Name(context.displayName)) } // テストメソッドの実行後にトランザクションをロールバックする override fun afterTestExecution(context: ExtensionContext) { transactionManager.rollback() } // テストクラスのコンストラクタの型をチェックする override fun supportsParameter( parameterContext: ParameterContext, extensionContext: ExtensionContext, ): Boolean = parameterContext.parameter.type === JdbcDatabase :: class .java // テストクラスのコンストラクタに db を渡す override fun resolveParameter( parameterContext: ParameterContext, extensionContext: ExtensionContext, ): Any = db } このクラスのポイントは次のとおりです。 システムプロ パティから JDBC 接続URLを取得しKomapperのデータベース インスタンス を作成する データベース インスタンス はテストクラスのコンスト ラク タに渡す 最初のテストを実行する前に一度だけ cusotmers テーブルを作成する テストメソッドの実行前に トランザクション を開始し、終了後に ロールバック を行う(テスト間の影響を生じさせない) ビジネスロジック のテストコード ビジネスロジック のテストコードは次のようになります。 package example import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.komapper.jdbc.JdbcDatabase @ExtendWith (DatabaseTestSupport :: class ) class CustomerServiceTest(db: JdbcDatabase) { // テスト対象のサービスクラスをインスタンス化する private val customerService = CustomerService(db) @Test fun shouldGetCustomers() { customerService.createCustomer(Customer( 1L , "George" )) customerService.createCustomer(Customer( 2L , "John" )) val customers = customerService.getAllCustomers() assertEquals( 2 , customers.size) } } このクラスのポイントは次のとおりです @ExtendWith で上述した DatabaseTestSupport クラスを指定する コンスト ラク タでデータベース インスタンス を受け取りサービスクラスのコンスト ラク タに渡す テストメソッドの shouldGetCustomers では Customer エンティティを2件追加した後で全件を取得し、取得した件数が2件であったかどうかを検証しています。 プロパティの設定 gradle.propetiesに jdbc .urlをキーとして JDBC の接続URLを設定します。 jdbc.url=jdbc:tc:postgresql:15-alpine:///test?TC_DAEMON=true 接続URLのポイントは次のとおりです。 tc: がTestcontainersを使うことを示す postgresql:15-alpine で利用するデータベースとDockerイメージが決まる test は接続先のデータベースの名前(Testcontainersのデフォルトのデータベース名) TC_DAEMON=true はデータベースをデーモンモードで動かすことを示す Testcontainersは JDBC ドライバが接続URLから自動検出される機能を使ってコンテナを自動で起動します。 データベースをデーモンモードで動かすと JVM がシャットダウンするまで起動したままにできます。つまり、テストメソッドやテストクラスごとにデータベースインスタを起動/停止するよりもテストの実行時間を短縮できます。 テストの実行 以下のコマンドをターミナルに打ち込むことでテストを実行できます。このとき、gradle.propetiesに記載した jdbc.url プロパティが暗黙的に利用されます。 ./gradlew test 利用するDockerイメージは簡単に変更できます。例えば、latestを使いたい場合はプロパティで次のように接続URLを明示的に指定します。 ./gradlew test -Pjdbc . url =jdbc:tc:postgresql:latest:/// test ? TC_DAEMON =true 通常の接続URLを指定すれば、Testcontaners上のデータベースではなくローカルのデータベースに繋ぐこともできます。 ./gradlew test -Pjdbc . url =jdbc:postgresql://localhost:5432/komapper? user =postgres テストが成功したことの確認 テストが成功すると「BUILD SUCCESSFUL」の文字がコンソールに出力されます。ただこれだけでは本当にテストが実施されたのか、テストが成功したのか確証を持てないかもしれません。その場合は以下のコマンドを打つなどしてテストで生成されるレポートをブラウザで開きましょう。 open build/reports/tests/ test /classes/example.CustomerServiceTest.html ブラウザ上で以下のような表示を確認できれば間違いなくテストが成功していると言えます。 上記ではGradleコマンドをターミナルに打ち込んでテストを実行すると説明しましたが、 IntelliJ IDEAなどの IDE からテストを実行しても構いません。その場合、次のような表示を IDE 上で確認できればテストが成功しています。 本記事で伝えたいこと(再) Testcontainersのオススメの使い方をサンプルコードを交えて紹介しました。 以下、改めて本記事で伝えたい3点について説明をします。 TestContainersの API よりも JDBC の接続URLを使おう Testcontainersの API を直接呼びだすサンプルコードをよく見かけますが、Testcontainersは JDBC の接続URLから特定のデータベースを起動できます。接続URLを使うことでDockerイメージを切り替えたりローカルの環境に接続したりが簡単になります。 なお、Testcontainersの API を直接呼びだす方法を否定したいわけではありません。要件によっては直接 API を呼びだす方法のほうが使いやすいこともあるでしょう。 データベースはデーモンモードで起動しよう 接続URLのオプションで TC_DAEMON=true パラメータを指定するとデーモンモードで起動できます。デーモンモードにするとデータベース インスタンス の起動と終了をテストを通して一度きりにできるのでテストの実行時間を短縮できます。 Testcontainersの API を直接呼びだす場合は、 Singleton containers に記載の方法で同等のことが実現できます。 テスト同士が影響しないようにテスト毎に ロールバック を実行しよう デーモンモードで起動すると、あるテストにおけるデータベースの変更が他のテストに影響することがあり得ます。テスティング フレームワーク やデータベースアクセスの フレームワーク を組み合わせて、テスト実行前の トランザクション 開始と終了時の ロールバック を徹底しましょう。 なお、テストによってはシーケンスのインクリメントや DDL の実行など ロールバック できない変更を加えることがあるかもしれません。その場合は別途対応が必要になります。 最後に 本記事で紹介したコードは GitHub Actions上で特別な設定をすることなく動作します。サンプルコードを含めた リポジトリ https://github.com/nakamura-to/testcontainers-demo には、 GitHub Actionsのワークフローも含めています。参考にしていただければ幸いです。 本記事をお読みいただきありがとうございました。 私たちの アドベントカレンダー では土曜日と日曜日はお休みしているので、次回の記事は月曜日に公開予定です。12月11日、月曜日の記事もぜひご覧ください。 私たちは一緒に働いてくれる仲間を募集しています! フルサイクルエンジニア 執筆: @nakamura.toshihiro 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
こんにちは、X イノベーション 本部ソフトウェアデザインセンターの中村です。 本記事は 電通国際情報サービス Advent Calendar 2023 の12月8日の記事です。 皆さんはデータベースアクセスを行うアプリケーションの ユニットテスト やインテグレーションテストをどのように実施していますか?絶対の正解はありませんが、テストの効率性や正確性などを考慮して様々な工夫や検討がなされる領域だと思います。例えば次のような戦略があります。 データベースアクセス部分をモックにする 運用時のデータベースよりも高速なインメモリデータベースを使う(例えば H2 Database Engine など) 開発者のローカル環境に運用環境と同等のテスト用データベースをインストールする 本記事では、 Testcontainers を使ってデータベースアクセスを伴うテストを効率的に実施する方法をコードを交えながら紹介します。 本記事で伝えたいこと 最初に、本記事で伝えたいことを簡単にまとめておきます。 TestContainersの API よりも JDBC の接続URLを使おう データベースはデーモンモードで起動しよう テスト同士が影響しないようにテスト毎に ロールバック を実行しよう Testcontainersとは? Testcontainersは、Dockerコンテナで実行できるデータベースなどのソフトウェアに関して軽量で使い捨て可能な インスタンス を提供するための オープンソース フレームワーク です。 この フレームワーク を使うと、運用環境と同等のデータベース インスタンス をテスト環境で何度でも簡単に再現し利用できます。 Testcontainersでは、 Java 、Go、.NET、Node.jsなど多数の プログラミング言語 がサポートされています。 前提 本記事の前提は以下のとおりです。 Testcontainers for Java を使う Dockerを動かす環境としてはDocker Desktopを使う プログラミング言語 にはKotlinを使う データベースには PostgreSQL を使う データベースアクセスの フレームワーク には Komapper を使う ビルドツールにはGradle Wrapperを使う(Gradleのバージョンは以下のとおり) ./gradlew -v ------------------------------------------------------------ Gradle 8.5 ------------------------------------------------------------ Build time: 2023-11-29 14:08:57 UTC Revision: 28aca86a7180baa17117e0e5ba01d8ea9feca598 Kotlin: 1.9.20 Groovy: 3.0.17 Ant: Apache Ant(TM) version 1.10.13 compiled on January 4 2023 JVM: 21.0.1 (Azul Systems, Inc. 21.0.1+12-LTS) OS: Mac OS X 12.6 x86_64 データベースアクセスの フレームワーク であるKomapperについて少し補足をします。Komapperは、 MySQL 、 PostgreSQL 、 Oracle Databaseなどの代表的なリレーショナルデータベースに対応した O/Rマッピング フレームワーク です。Kotlin製の代表的な O/Rマッピング フレームワーク である Exposed ほどの 知名度 はありませんが機能性や使いやすさでは負けていません(と、Komapperの作者である私は考えています😁)。Komapperでは様々なデータベースとの稼働確認をTestcontainersを用いて行っています。 本記事にはデータベース、 フレームワーク 、ビルドツールに強く依存した説明はありませんので適宜お好みの環境に置き換えてお読みいただけます。ただし、 プログラミング言語 については JVM 言語以外に読み替えるのは難しいかもしれません。 本記事で示すサンプルコードは Getting started with Testcontainers for Java を下敷きにしています。ぜひ見比べてみてください。 Gradleの設定 以下のようなbuild.gradle.ktsを用意します。 plugins { application id( "com.google.devtools.ksp" ) version "1.9.21-1.0.15" kotlin( "jvm" ) version "1.9.21" } group = "org.example" version = "1.0-SNAPSHOT" repositories { mavenCentral() } dependencies { // Komapperの設定 platform( "org.komapper:komapper-platform:1.15.0" ).let { implementation(it) ksp(it) } implementation( "org.komapper:komapper-starter-jdbc" ) implementation( "org.komapper:komapper-dialect-postgresql-jdbc" ) ksp( "org.komapper:komapper-processor" ) // Testcontainersの設定 testImplementation(platform( "org.testcontainers:testcontainers-bom:1.19.3" )) testRuntimeOnly( "org.testcontainers:postgresql" ) // JUnitの設定 testImplementation( "org.junit.jupiter:junit-jupiter-api:5.9.2" ) testRuntimeOnly( "org.junit.jupiter:junit-jupiter-engine:5.9.2" ) } tasks.getByName<Test>( "test" ) { useJUnitPlatform() // GradleのプロパティをJavaのシステムプロパティに引き継ぐ val jdbcUrl = project.property( "jdbc.url" ) ?: error( "jdbc.url not found" ) systemProperty( "jdbc.url" , jdbcUrl) } ポイントは以下のとおりです。 利用するライブラリ(Kotlin、Komapper、Testcontainers、 JUnit )への依存を示す JDBC の接続URLをGradleのプロパティを介してアプリケーションに渡す ビジネスロジック データベース上の customers テーブルに対応する Customer エンティティクラスを定義します。 package example import org.komapper. annotation .KomapperEntity import org.komapper. annotation .KomapperId import org.komapper. annotation .KomapperTable @KomapperEntity @KomapperTable ( "customers" ) data class Customer( @KomapperId val id: Long , val name: String ) Komapperが認識できるようにKomapperの アノテーション を付与しています。 Customer エンティティクラスを使ってデータの追加や取得を行うサービスクラスは次のようになります。 package example import org.komapper.core.dsl.Meta import org.komapper.core.dsl.QueryDsl import org.komapper.jdbc.JdbcDatabase class CustomerService( private val db: JdbcDatabase) { // Customerエンティティクラスのメタモデル private val c = Meta.customer fun createCustomer(customer: Customer) { db.runQuery { // 対応するSQL: insert into customers (id, name) values (?, ?) QueryDsl.insert(c).single(customer) } } fun getAllCustomers(): List <Customer> { return db.runQuery { // 対応するSQL: select t0_.id, t0_.name from customers as t0_ QueryDsl.from(c) } } } データの追加や取得にはKomapperの API を使います。 API から発行する SQL はコード内のコメントに示したとおりです。 テストコード Getting started with Testcontainers for Java では、テストを制御するコードとテストコードが同じクラスに記述されていますが、本記事では分離して示します。 テストを制御するためのコード テストを制御するコードは以下のようになります。このコードは一度書けば複数のテストクラスから再利用できます。 package example import org.junit.jupiter.api.extension.AfterTestExecutionCallback import org.junit.jupiter.api.extension.BeforeAllCallback import org.junit.jupiter.api.extension.BeforeTestExecutionCallback import org.junit.jupiter.api.extension.ExtensionContext import org.junit.jupiter.api.extension.ParameterContext import org.junit.jupiter.api.extension.ParameterResolver import org.komapper.core.dsl.Meta import org.komapper.core.dsl.QueryDsl import org.komapper.jdbc.JdbcDatabase import org.komapper.tx.core.TransactionProperty import org.komapper.tx.jdbc.JdbcTransactionSession class DatabaseTestSupport : BeforeAllCallback, BeforeTestExecutionCallback, AfterTestExecutionCallback, ParameterResolver { companion object { @Volatile private var initialized: Boolean = false // Komapperのデータベース private val db = JdbcDatabase(url = System.getProperty( "jdbc.url" ) ?: error( "jdbc.url not found" )) // Komapperのトランザクションマネージャー private val transactionManager = run { val session = db.config.session as JdbcTransactionSession session.transactionManager } } // 最初のテストを実行する前に一度だけ cusotmers テーブルを作成する override fun beforeAll(context: ExtensionContext) { if ( ! initialized) { initialized = true db.runQuery { // 対応するSQL: create table if not exists customers (id bigint not null, name text not null, constraint pk_customers primary key(id)) QueryDsl.create(Meta.customer) } } } // テストメソッドの実行前にトランザクションを開始する override fun beforeTestExecution(context: ExtensionContext) { transactionManager.begin(TransactionProperty.Name(context.displayName)) } // テストメソッドの実行後にトランザクションをロールバックする override fun afterTestExecution(context: ExtensionContext) { transactionManager.rollback() } // テストクラスのコンストラクタの型をチェックする override fun supportsParameter( parameterContext: ParameterContext, extensionContext: ExtensionContext, ): Boolean = parameterContext.parameter.type === JdbcDatabase :: class .java // テストクラスのコンストラクタに db を渡す override fun resolveParameter( parameterContext: ParameterContext, extensionContext: ExtensionContext, ): Any = db } このクラスのポイントは次のとおりです。 システムプロ パティから JDBC 接続URLを取得しKomapperのデータベース インスタンス を作成する データベース インスタンス はテストクラスのコンスト ラク タに渡す 最初のテストを実行する前に一度だけ cusotmers テーブルを作成する テストメソッドの実行前に トランザクション を開始し、終了後に ロールバック を行う(テスト間の影響を生じさせない) ビジネスロジック のテストコード ビジネスロジック のテストコードは次のようになります。 package example import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.komapper.jdbc.JdbcDatabase @ExtendWith (DatabaseTestSupport :: class ) class CustomerServiceTest(db: JdbcDatabase) { // テスト対象のサービスクラスをインスタンス化する private val customerService = CustomerService(db) @Test fun shouldGetCustomers() { customerService.createCustomer(Customer( 1L , "George" )) customerService.createCustomer(Customer( 2L , "John" )) val customers = customerService.getAllCustomers() assertEquals( 2 , customers.size) } } このクラスのポイントは次のとおりです @ExtendWith で上述した DatabaseTestSupport クラスを指定する コンスト ラク タでデータベース インスタンス を受け取りサービスクラスのコンスト ラク タに渡す テストメソッドの shouldGetCustomers では Customer エンティティを2件追加した後で全件を取得し、取得した件数が2件であったかどうかを検証しています。 プロパティの設定 gradle.propetiesに jdbc .urlをキーとして JDBC の接続URLを設定します。 jdbc.url=jdbc:tc:postgresql:15-alpine:///test?TC_DAEMON=true 接続URLのポイントは次のとおりです。 tc: がTestcontainersを使うことを示す postgresql:15-alpine で利用するデータベースとDockerイメージが決まる test は接続先のデータベースの名前(Testcontainersのデフォルトのデータベース名) TC_DAEMON=true はデータベースをデーモンモードで動かすことを示す Testcontainersは JDBC ドライバが接続URLから自動検出される機能を使ってコンテナを自動で起動します。 データベースをデーモンモードで動かすと JVM がシャットダウンするまで起動したままにできます。つまり、テストメソッドやテストクラスごとにデータベースインスタを起動/停止するよりもテストの実行時間を短縮できます。 テストの実行 以下のコマンドをターミナルに打ち込むことでテストを実行できます。このとき、gradle.propetiesに記載した jdbc.url プロパティが暗黙的に利用されます。 ./gradlew test 利用するDockerイメージは簡単に変更できます。例えば、latestを使いたい場合はプロパティで次のように接続URLを明示的に指定します。 ./gradlew test -Pjdbc . url =jdbc:tc:postgresql:latest:/// test ? TC_DAEMON =true 通常の接続URLを指定すれば、Testcontaners上のデータベースではなくローカルのデータベースに繋ぐこともできます。 ./gradlew test -Pjdbc . url =jdbc:postgresql://localhost:5432/komapper? user =postgres テストが成功したことの確認 テストが成功すると「BUILD SUCCESSFUL」の文字がコンソールに出力されます。ただこれだけでは本当にテストが実施されたのか、テストが成功したのか確証を持てないかもしれません。その場合は以下のコマンドを打つなどしてテストで生成されるレポートをブラウザで開きましょう。 open build/reports/tests/ test /classes/example.CustomerServiceTest.html ブラウザ上で以下のような表示を確認できれば間違いなくテストが成功していると言えます。 上記ではGradleコマンドをターミナルに打ち込んでテストを実行すると説明しましたが、 IntelliJ IDEAなどの IDE からテストを実行しても構いません。その場合、次のような表示を IDE 上で確認できればテストが成功しています。 本記事で伝えたいこと(再) Testcontainersのオススメの使い方をサンプルコードを交えて紹介しました。 以下、改めて本記事で伝えたい3点について説明をします。 TestContainersの API よりも JDBC の接続URLを使おう Testcontainersの API を直接呼びだすサンプルコードをよく見かけますが、Testcontainersは JDBC の接続URLから特定のデータベースを起動できます。接続URLを使うことでDockerイメージを切り替えたりローカルの環境に接続したりが簡単になります。 なお、Testcontainersの API を直接呼びだす方法を否定したいわけではありません。要件によっては直接 API を呼びだす方法のほうが使いやすいこともあるでしょう。 データベースはデーモンモードで起動しよう 接続URLのオプションで TC_DAEMON=true パラメータを指定するとデーモンモードで起動できます。デーモンモードにするとデータベース インスタンス の起動と終了をテストを通して一度きりにできるのでテストの実行時間を短縮できます。 Testcontainersの API を直接呼びだす場合は、 Singleton containers に記載の方法で同等のことが実現できます。 テスト同士が影響しないようにテスト毎に ロールバック を実行しよう デーモンモードで起動すると、あるテストにおけるデータベースの変更が他のテストに影響することがあり得ます。テスティング フレームワーク やデータベースアクセスの フレームワーク を組み合わせて、テスト実行前の トランザクション 開始と終了時の ロールバック を徹底しましょう。 なお、テストによってはシーケンスのインクリメントや DDL の実行など ロールバック できない変更を加えることがあるかもしれません。その場合は別途対応が必要になります。 最後に 本記事で紹介したコードは GitHub Actions上で特別な設定をすることなく動作します。サンプルコードを含めた リポジトリ https://github.com/nakamura-to/testcontainers-demo には、 GitHub Actionsのワークフローも含めています。参考にしていただければ幸いです。 本記事をお読みいただきありがとうございました。 私たちの アドベントカレンダー では土曜日と日曜日はお休みしているので、次回の記事は月曜日に公開予定です。12月11日、月曜日の記事もぜひご覧ください。 私たちは一緒に働いてくれる仲間を募集しています! フルサイクルエンジニア 執筆: @nakamura.toshihiro 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
こんにちは。金融ソリューション事業部の宮原です。本記事は 電通国際情報サービス Advent Calendar 2023 7日目の記事となります。 みなさん、Go言語で並行処理は利用されているでしょうか?Go言語はゴルーチンやチャネルといった独自の並行処理機構を備えており、比較的簡単に並行処理を導入できます。 しかしながら、ゴルーチンやチャネルの仕組みを理解し、並行処理のパターンを独自に実装していくのは意外と難しいものです。 Go言語ではsyncパッケージをはじめとして、並行処理のパターンを簡単に導入できるようにライブラリとして提供しています。 本記事ではGo言語が提供しているライブラリの中でも準標準パッケージの位置付けである golang.org/x/sync/errgroup パッケージを利用した並行処理の実装方法をご紹介したいと思います。 前提 まずはシンプルに記述してみる エラーを考慮しながら関数化してみる キャンセルを検討してみる 同時実行数を制御する まとめ 前提 以降では「特定のURLにHTTPリク エス トを並行で送信しながら、全てのURLへのHTTPリク エス トが終わるまで待ち合わせる」という処理を前提としてサンプルコードを記載します。 今回のサンプルコードはsyncパッケージの サンプルコード を一部改変して作成しています。 また、Goのバージョンについては1.21.3を前提としています。 まずはシンプルに記述してみる package main import ( "fmt" "net/http" "sync" ) func main() { var wg sync.WaitGroup var urls = [] string { "http://www.golang.org/" , "http://www.google.com/" , "http://www.example.com/" , } for i, url := range urls { i, url := i, url wg.Add( 1 ) go func () { defer wg.Done() resp, err := http.Get(url) if err != nil { fmt.Println(err) return } defer resp.Body.Close() fmt.Printf( "%d番目のリクエスト: %s \n " , i+ 1 , resp.Status) }() } wg.Wait() } まずはシンプルな形で処理を実装してみます。最初の例ではerrgroupパッケージは利用せず、syncパッケージのsync.WaitGroupを利用して処理を記述します。 後ほど詳しく説明しますが、errgroupパッケージはsync.WaitGroupの機能を拡張したものになります。そのため、まずはsync.WaitGroupをよく理解することが重要です。 処理としてはforループとgoキーワードを利用しゴルーチンを起動して、3つのURLに対して並行にリク エス トを送信しています。 sync.WaitGroupを理解する上で重要なのはAddメソッド、Doneメソッド、Waitメソッドです。 今回のプログラムではgoキーワードでゴルーチンを起動する前にAddメソッドを呼び出し、処理が終わった後にDoneメソッドを呼び出しています。 そしてループの外側でWaitメソッドを呼び出し、すべてのゴルーチンが完了するのを待ちます。 sync.WaitGroupではAddメソッドで内部のカウンタをインクリメントし、Doneメソッドで内部のカウンタをデクリメントします。 そしてWaitメソッドでは内部のカウンタを監視し、カウンタが0になるまで待つようになっています。 実行結果は以下です。今回の実行では2番目、3番目、1番目の順で処理が完了したようです。処理が並行に行われているため、この出力は実行毎に変わる可能性があります。 2 番目のリクエスト: 200 OK 3 番目のリクエスト: 200 OK 1 番目のリクエスト: 200 OK sync.WaitGroupを利用するとシンプルに並行処理を記述できます。チャネルの処理を考慮する必要がなく、処理の流れも比較的イメージしやすいです。 エラーを考慮しながら関数化してみる 先ほどの例ではsync.WaitGroupを利用して処理を記述しました。 今度はURLを並行で処理する部分を関数化する例を考えてみましょう。 実装している中で特定の処理を関数化したくなったり、エラーハンドリングをしたくなったりすることはよくあります。 今回は以下のような関数を考えてみます func CallURL(urls [] string ) error リク エス ト先のURLを引数にとり、URLに対して並行に処理を行うようなCallURLという関数を考えてみます。 また、関数内でエラーが発生した場合にはエラーを上位の関数に渡します。 しかし悩ましいのがエラーの扱いです。goキーワードを使った関数から直接エラーを受け取ることはできませんし、sync.WaitGroupのWaitメソッドを利用してエラーを取得することもできません。 そこで便利なのが golang.org/x/sync/errgroup パッケージのerrgroup.Groupです。 errgroup.Groupを利用することでsync.WaitGroupと同等の機能を利用しながらエラーハンドリングを行うことが可能です。このerrgroup.Groupを利用して上記の関数を記述してみます。 package main import ( "fmt" "net/http" "golang.org/x/sync/errgroup" ) func main() { var urls = [] string { "http://www.golang.org/" , "http://www.google.com/" , "http://www.example.com/" , } if err := CallURL(urls); err != nil { fmt.Println(err) } } func CallURL(urls [] string ) error { var eg errgroup.Group for i, url := range urls { i, url := i, url eg.Go( func () error { resp, err := http.Get(url) if err != nil { return err } defer resp.Body.Close() fmt.Printf( "%d番目のリクエスト: %s \n " , i+ 1 , resp.Status) return nil }) } if err := eg.Wait(); err != nil { return err } return nil } errgroup.Groupはsync.WaitGroupを内部に持つ構造体です。 errgroup.Groupを利用した今回のサンプルコードではAddメソッド、Doneメソッドやゴルーチンの起動処理は記載していません。 これらの処理は全てGoメソッドの中で呼び出されているため、明示的に呼びだす必要はありません。 Goメソッドに渡した関数は内部でgoキーワードを使って並行に起動するようになっています。 また、Goメソッドにはエラーを返り値とした関数を渡し、Waitメソッドでは関数からのエラーを受け取れるようになっています。Goメソッドで起動した関数の中でエラーが発生した場合にWaitメソッド経由でエラーを受け取ることができます。 ここでポイントなのが、複数のエラーが発生した場合でもWaitメソッドで確認できるエラーは一つだけということです。 Waitメソッドでは複数の関数の中で最初に発生したエラーしか確認することができず、その他のエラーについては確認することはできません。 キャンセルを検討してみる 先ほどの例では一つの関数でエラーが発生しても、他の関数はそのエラーを気にせず処理を続けるようになっていました。 しかしながら場合によってはエラーが発生した場合に他の関数の処理を停止させたい、キャンセルしたい場合もあると思います。 実はキャンセルに関する機能もerrgroup.Groupには備わっています。 一つの関数でエラーが発生した場合に、他の関数の処理を停止するサンプルを作成してみます。 package main import ( "context" "fmt" "net/http" "golang.org/x/sync/errgroup" ) func main() { var urls = [] string { "http://www.golang.org/" , "http://www.google.com/" , "http://www.example.com/" , } if err := CallURL(urls); err != nil { fmt.Println(err) } } func CallURL(urls [] string ) error { eg, ctx := errgroup.WithContext(context.Background()) for i, url := range urls { i, url := i, url eg.Go( func () error { req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil ) resp, err := http.DefaultClient.Do(req) if err != nil { return err } defer resp.Body.Close() fmt.Printf( "%d番目のリクエスト: %s \n " , i+ 1 , resp.Status) return nil }) } if err := eg.Wait(); err != nil { return err } return nil } 今回の例ではerrgroup.WithContext関数を最初に呼び出しています。 返り値はerrgroup.Groupとcontext.Contextです。 あとは返り値のerrgroup.Groupとcontext.Contextを利用して、処理を実装します。 今回の例では API 呼び出し部分も少し変わっています。htttp.NewRequestWithContext関数とhttp.DefaultClient.Doメソッドを呼びだすようにしています。 これらの関数を利用することで引数のcontext.Contextがキャンセルされているかを監視しながら処理を進めるようにしています。 http.DefaultClient.Doメソッド内部ではcontext.Contextのキャンセルを監視し、キャンセルされている場合は処理を終了するようになっています。 では肝心のcontext.Contextのキャンセル処理はどこで実行されているのでしょうか? 実はGoメソッドの内部で関数がエラーを返した場合にcontext.Contextのキャンセルを実行するようになっています。 WithContext関数の中ではcontext.WithCancelCause関数が呼び出されており、WithCancelCause関数の返り値のキャンセル関数がerrgroup.Groupのフィールドにセットされます。 Goメソッドの内部ではエラーが発生した場合に、このキャンセル関数を呼びだすことでcontext.Contextをキャンセルするようになっています。 (Goのバージョンが1.20以上の場合、WithContext関数の内部ではcontext.WithCancelCause関数が呼び出されますが、1.20以前の場合はcontext.WithCancel関数が呼び出されます) 同時実行数を制御する errgroup.GroupにはGoメソッドで起動するゴルーチンの同時実行数を制御する機能があります。 例えば特定のURLに複数のリク エス トを投げる際に、負荷を考慮しながらリク エス トを投げたい場合などがあると思います。そういった際にはこの同時実行数制御の仕組みが役に立ちます。 サンプルコードを見てみましょう。 package main import ( "context" "fmt" "net/http" "golang.org/x/sync/errgroup" ) func main() { var urls = [] string { "http://www.golang.org/" , "http://www.google.com/" , "http://www.example.com/" , } if err := CallURL(urls); err != nil { fmt.Println(err) } } func CallURL(urls [] string ) error { eg, ctx := errgroup.WithContext(context.Background()) eg.SetLimit( 2 ) for i, url := range urls { i, url := i, url eg.Go( func () error { req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil ) resp, err := http.DefaultClient.Do(req) if err != nil { return err } defer resp.Body.Close() fmt.Printf( "%d番目のリクエスト: %s \n " , i+ 1 , resp.Status) return nil }) } if err := eg.Wait(); err != nil { return err } return nil } 一つ前の例から変わっている箇所は一箇所です。 今回の例ではerrgroup.GroupのSetLimitメソッドを呼び出しています。引数で同時実行数を渡すと、Goメソッド内で起動されるゴルーチンの数が制限されます。今回のサンプルコードではゴルーチンの同時実行数を2としています。 errgroup.Groupの内部ではバッファ付きチャネルを利用して、ゴルーチンの同時実行数を制御しています。 Goメソッド内部でゴルーチン起動前にバッファ付きチャネルに値を追加し、処理完了後にチャネルから値を取り出しています。バッファがいっぱいになった場合はそのタイミングで処理が停止するようになっています。 このようにSetLimitメソッドを使うだけでゴルーチンの同時実行数を制御できます。 まとめ 今回の記事では golang.org/x/sync/errgroup パッケージを利用した並行処理の実装について紹介しました。 errgroupパッケージを利用することで簡単に並行処理を記述できるだけではなくエラーハンドリング、キャンセル処理、ゴルーチンの同時実行数制御など並行処理のパターンを導入できます。 みなさんも並行処理を実装する際にはぜひ golang.org/x/sync/errgroup パッケージの利用を検討してみてください。 私たちは一緒に働いてくれる仲間を募集しています! 募集職種一覧 執筆: @miyahara.hikaru 、レビュー: @yamashita.tsuyoshi ( Shodo で執筆されました )
こんにちは。金融ソリューション事業部の宮原です。本記事は 電通国際情報サービス Advent Calendar 2023 7日目の記事となります。 みなさん、Go言語で並行処理は利用されているでしょうか?Go言語はゴルーチンやチャネルといった独自の並行処理機構を備えており、比較的簡単に並行処理を導入できます。 しかしながら、ゴルーチンやチャネルの仕組みを理解し、並行処理のパターンを独自に実装していくのは意外と難しいものです。 Go言語ではsyncパッケージをはじめとして、並行処理のパターンを簡単に導入できるようにライブラリとして提供しています。 本記事ではGo言語が提供しているライブラリの中でも準標準パッケージの位置付けである golang.org/x/sync/errgroup パッケージを利用した並行処理の実装方法をご紹介したいと思います。 前提 まずはシンプルに記述してみる エラーを考慮しながら関数化してみる キャンセルを検討してみる 同時実行数を制御する まとめ 前提 以降では「特定のURLにHTTPリク エス トを並行で送信しながら、全てのURLへのHTTPリク エス トが終わるまで待ち合わせる」という処理を前提としてサンプルコードを記載します。 今回のサンプルコードはsyncパッケージの サンプルコード を一部改変して作成しています。 また、Goのバージョンについては1.21.3を前提としています。 まずはシンプルに記述してみる package main import ( "fmt" "net/http" "sync" ) func main() { var wg sync.WaitGroup var urls = [] string { "http://www.golang.org/" , "http://www.google.com/" , "http://www.example.com/" , } for i, url := range urls { i, url := i, url wg.Add( 1 ) go func () { defer wg.Done() resp, err := http.Get(url) if err != nil { fmt.Println(err) return } defer resp.Body.Close() fmt.Printf( "%d番目のリクエスト: %s \n " , i+ 1 , resp.Status) }() } wg.Wait() } まずはシンプルな形で処理を実装してみます。最初の例ではerrgroupパッケージは利用せず、syncパッケージのsync.WaitGroupを利用して処理を記述します。 後ほど詳しく説明しますが、errgroupパッケージはsync.WaitGroupの機能を拡張したものになります。そのため、まずはsync.WaitGroupをよく理解することが重要です。 処理としてはforループとgoキーワードを利用しゴルーチンを起動して、3つのURLに対して並行にリク エス トを送信しています。 sync.WaitGroupを理解する上で重要なのはAddメソッド、Doneメソッド、Waitメソッドです。 今回のプログラムではgoキーワードでゴルーチンを起動する前にAddメソッドを呼び出し、処理が終わった後にDoneメソッドを呼び出しています。 そしてループの外側でWaitメソッドを呼び出し、すべてのゴルーチンが完了するのを待ちます。 sync.WaitGroupではAddメソッドで内部のカウンタをインクリメントし、Doneメソッドで内部のカウンタをデクリメントします。 そしてWaitメソッドでは内部のカウンタを監視し、カウンタが0になるまで待つようになっています。 実行結果は以下です。今回の実行では2番目、3番目、1番目の順で処理が完了したようです。処理が並行に行われているため、この出力は実行毎に変わる可能性があります。 2 番目のリクエスト: 200 OK 3 番目のリクエスト: 200 OK 1 番目のリクエスト: 200 OK sync.WaitGroupを利用するとシンプルに並行処理を記述できます。チャネルの処理を考慮する必要がなく、処理の流れも比較的イメージしやすいです。 エラーを考慮しながら関数化してみる 先ほどの例ではsync.WaitGroupを利用して処理を記述しました。 今度はURLを並行で処理する部分を関数化する例を考えてみましょう。 実装している中で特定の処理を関数化したくなったり、エラーハンドリングをしたくなったりすることはよくあります。 今回は以下のような関数を考えてみます func CallURL(urls [] string ) error リク エス ト先のURLを引数にとり、URLに対して並行に処理を行うようなCallURLという関数を考えてみます。 また、関数内でエラーが発生した場合にはエラーを上位の関数に渡します。 しかし悩ましいのがエラーの扱いです。goキーワードを使った関数から直接エラーを受け取ることはできませんし、sync.WaitGroupのWaitメソッドを利用してエラーを取得することもできません。 そこで便利なのが golang.org/x/sync/errgroup パッケージのerrgroup.Groupです。 errgroup.Groupを利用することでsync.WaitGroupと同等の機能を利用しながらエラーハンドリングを行うことが可能です。このerrgroup.Groupを利用して上記の関数を記述してみます。 package main import ( "fmt" "net/http" "golang.org/x/sync/errgroup" ) func main() { var urls = [] string { "http://www.golang.org/" , "http://www.google.com/" , "http://www.example.com/" , } if err := CallURL(urls); err != nil { fmt.Println(err) } } func CallURL(urls [] string ) error { var eg errgroup.Group for i, url := range urls { i, url := i, url eg.Go( func () error { resp, err := http.Get(url) if err != nil { return err } defer resp.Body.Close() fmt.Printf( "%d番目のリクエスト: %s \n " , i+ 1 , resp.Status) return nil }) } if err := eg.Wait(); err != nil { return err } return nil } errgroup.Groupはsync.WaitGroupを内部に持つ構造体です。 errgroup.Groupを利用した今回のサンプルコードではAddメソッド、Doneメソッドやゴルーチンの起動処理は記載していません。 これらの処理は全てGoメソッドの中で呼び出されているため、明示的に呼びだす必要はありません。 Goメソッドに渡した関数は内部でgoキーワードを使って並行に起動するようになっています。 また、Goメソッドにはエラーを返り値とした関数を渡し、Waitメソッドでは関数からのエラーを受け取れるようになっています。Goメソッドで起動した関数の中でエラーが発生した場合にWaitメソッド経由でエラーを受け取ることができます。 ここでポイントなのが、複数のエラーが発生した場合でもWaitメソッドで確認できるエラーは一つだけということです。 Waitメソッドでは複数の関数の中で最初に発生したエラーしか確認することができず、その他のエラーについては確認することはできません。 キャンセルを検討してみる 先ほどの例では一つの関数でエラーが発生しても、他の関数はそのエラーを気にせず処理を続けるようになっていました。 しかしながら場合によってはエラーが発生した場合に他の関数の処理を停止させたい、キャンセルしたい場合もあると思います。 実はキャンセルに関する機能もerrgroup.Groupには備わっています。 一つの関数でエラーが発生した場合に、他の関数の処理を停止するサンプルを作成してみます。 package main import ( "context" "fmt" "net/http" "golang.org/x/sync/errgroup" ) func main() { var urls = [] string { "http://www.golang.org/" , "http://www.google.com/" , "http://www.example.com/" , } if err := CallURL(urls); err != nil { fmt.Println(err) } } func CallURL(urls [] string ) error { eg, ctx := errgroup.WithContext(context.Background()) for i, url := range urls { i, url := i, url eg.Go( func () error { req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil ) resp, err := http.DefaultClient.Do(req) if err != nil { return err } defer resp.Body.Close() fmt.Printf( "%d番目のリクエスト: %s \n " , i+ 1 , resp.Status) return nil }) } if err := eg.Wait(); err != nil { return err } return nil } 今回の例ではerrgroup.WithContext関数を最初に呼び出しています。 返り値はerrgroup.Groupとcontext.Contextです。 あとは返り値のerrgroup.Groupとcontext.Contextを利用して、処理を実装します。 今回の例では API 呼び出し部分も少し変わっています。htttp.NewRequestWithContext関数とhttp.DefaultClient.Doメソッドを呼びだすようにしています。 これらの関数を利用することで引数のcontext.Contextがキャンセルされているかを監視しながら処理を進めるようにしています。 http.DefaultClient.Doメソッド内部ではcontext.Contextのキャンセルを監視し、キャンセルされている場合は処理を終了するようになっています。 では肝心のcontext.Contextのキャンセル処理はどこで実行されているのでしょうか? 実はGoメソッドの内部で関数がエラーを返した場合にcontext.Contextのキャンセルを実行するようになっています。 WithContext関数の中ではcontext.WithCancelCause関数が呼び出されており、WithCancelCause関数の返り値のキャンセル関数がerrgroup.Groupのフィールドにセットされます。 Goメソッドの内部ではエラーが発生した場合に、このキャンセル関数を呼びだすことでcontext.Contextをキャンセルするようになっています。 (Goのバージョンが1.20以上の場合、WithContext関数の内部ではcontext.WithCancelCause関数が呼び出されますが、1.20以前の場合はcontext.WithCancel関数が呼び出されます) 同時実行数を制御する errgroup.GroupにはGoメソッドで起動するゴルーチンの同時実行数を制御する機能があります。 例えば特定のURLに複数のリク エス トを投げる際に、負荷を考慮しながらリク エス トを投げたい場合などがあると思います。そういった際にはこの同時実行数制御の仕組みが役に立ちます。 サンプルコードを見てみましょう。 package main import ( "context" "fmt" "net/http" "golang.org/x/sync/errgroup" ) func main() { var urls = [] string { "http://www.golang.org/" , "http://www.google.com/" , "http://www.example.com/" , } if err := CallURL(urls); err != nil { fmt.Println(err) } } func CallURL(urls [] string ) error { eg, ctx := errgroup.WithContext(context.Background()) eg.SetLimit( 2 ) for i, url := range urls { i, url := i, url eg.Go( func () error { req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil ) resp, err := http.DefaultClient.Do(req) if err != nil { return err } defer resp.Body.Close() fmt.Printf( "%d番目のリクエスト: %s \n " , i+ 1 , resp.Status) return nil }) } if err := eg.Wait(); err != nil { return err } return nil } 一つ前の例から変わっている箇所は一箇所です。 今回の例ではerrgroup.GroupのSetLimitメソッドを呼び出しています。引数で同時実行数を渡すと、Goメソッド内で起動されるゴルーチンの数が制限されます。今回のサンプルコードではゴルーチンの同時実行数を2としています。 errgroup.Groupの内部ではバッファ付きチャネルを利用して、ゴルーチンの同時実行数を制御しています。 Goメソッド内部でゴルーチン起動前にバッファ付きチャネルに値を追加し、処理完了後にチャネルから値を取り出しています。バッファがいっぱいになった場合はそのタイミングで処理が停止するようになっています。 このようにSetLimitメソッドを使うだけでゴルーチンの同時実行数を制御できます。 まとめ 今回の記事では golang.org/x/sync/errgroup パッケージを利用した並行処理の実装について紹介しました。 errgroupパッケージを利用することで簡単に並行処理を記述できるだけではなくエラーハンドリング、キャンセル処理、ゴルーチンの同時実行数制御など並行処理のパターンを導入できます。 みなさんも並行処理を実装する際にはぜひ golang.org/x/sync/errgroup パッケージの利用を検討してみてください。 私たちは一緒に働いてくれる仲間を募集しています! 募集職種一覧 執筆: @miyahara.hikaru 、レビュー: @yamashita.tsuyoshi ( Shodo で執筆されました )
どーもー!X イノベーション 本部 ソフトウェアデザインセンター セキュリティグループの福山です。 本記事は 電通国際情報サービス Advent Calendar 2023 6日目の記事となります。 念願だった AWS re:Invent現地参戦、ついに実現しました! 本レポートでは、セキュリティ関連のセッションに絞って紹介したいと思います。 re:Inventとは セッション内容 Builders' Session セッション名:Patch it up: Building a vulnerability management solution 感想 Chalk Talk セッション名:How to automate incident response with AWS security services & AI/ML 感想 最後に re:Inventとは 年に一度米国ラスベガスで開催される、 AWS 主催のIT業界最大規模のイベントです。 今年は日本から1000人以上、全体の参加者は約4〜5万人とのことで、規模の大きさがわかるかと思います。 re:Invent自体は2000以上のセッションが用意されているのと、 AWS やスポンサーと交流できるEXPOが主な内容です。 セッション内容 Builders' Session Builders' Sessionとは、少人数のグループで実際に手を動かしながら学んでいくタイプのセッションで、所要時間は1時間程度です。 各テーブルに AWS エキスパートがついており、気軽に質問できるのが特徴です。 参加したBuilders' Sessionのうち、1つ紹介します。 セッション名:Patch it up: Building a vulnerability management solution セッション概要: With thousands of new common vulnerabilities and exposures discovered every month, organizations can find it challenging to keep on top of their security using traditional, on-premises patching solutions. And the shift to containers and serverless can seem complex in an already diverse IT environment. Join this builders’ session to take a deep dive into patch management across a hybrid landscape with scenarios played out for containers, serverless, and virtual machines using AWS services. You must bring your laptop to participate. 複数タイプのリソースを 脆弱性 管理する方法を学ぶ。 Cloud9上でCDKの実行環境を構築して実行し、下図のような 脆弱性 管理の仕組みを構築していく。 ここでの 脆弱性 管理というのは、パッケージの 脆弱性 、コードの 脆弱性 、ネットワーク構成の 脆弱性 を指している。 リソース別に、EC2、ECR、Lambda、ネットワークは Amazon Inspectorで検出し、オンプレサーバは AWS Systems Manager Patch Managerで検出する。それらのFindingsをSecurity Hubに集約する。 Amazon Inspectorは検知までとなるが、 AWS Systems Manager Patch Managerは検知後のパッチ適用まで自動化することも可能。 感想 複数種類のリソースの 脆弱性 管理をするのは大変ですが、オンプレサーバ+ AWS リソースに限れば、Inspector、Patch Manager、Security Hubでここまでカバーできるんだと知りました。 しかもこれらをCloud9で構築できるから素晴らしいですね。 なお、Patch Mangerによるパッチ適用の自動化に関しては、いきなり本番で実行するのではなく、検証環境を用意して一度試してみた方がよさそうです。 あとは思いつき(要望)ですが、ソフトウェア名とバージョンを手動入力すると CPE (Common Platform Enumeration)が登録され、Inspector等でスキャンができるような機能があれば、管理の幅がさらに広がって最高なんだけどなぁ〜と思ったりしました。 さて、今回参加してみたBuilders' Sessionですが、それとは別で予約がすぐ埋まる人気セッションタイプの一つにWorkshopというものがあります。 WorkshopはBuilders' Sessionの長時間コースという位置付けになります。 Builder's SessionやWorkshopは現地でしか体験できないものなので、ぜひやっておくべきものだと思います。 Chalk Talk Chalk Talk は対話型のセッションです。後日オンラインで視聴できるBreakout Session同様、基本は AWS 側で講演を進めていきますが、参加者側から任意のタイミングで質問できます。そのため、Breakout Sessionより参加人数が制限されています。また、オンライン視聴では参加者からの質問が音声に含まれませんので、全て聞くには現地に参加するしかありません。 参加したChalk Talk のうち、1つを紹介します。 セッション名:How to automate incident response with AWS security services & AI/ML セッション概要: In this chalk talk , explore how generative AI and machine learning can be used alongside key AWS security services to enrich security analytics and automate incident response for security teams, helping to reduce the time to respond to security incidents and improve the developer experience. 顧客から頻繁に話題にあがるのは、インシデント対応フローを自動化したいということ。 検出を高速化するために生成AIを活用している。 Amazon Bedrockは VPC エンドポイントを介してデータをプライベートに保てる。 LLMをカスタマイズしたり、組織内のさまざまな状況で独自のLLMを構築する必要がある場合には Amazon Sage Makerを使用できる。 ここにいる皆さんがよく知っているであろうGuardDuty は2000のTOP AWS カスタマーのうち90%以上が利用している。 GuardDutyはECSランタイムモニタリング、EC2ランタイムモニタリングをサポートし、さらに多くのデータソースを収集できるようになった。コン トロール プレーンのログを側面からでなく、リソース上のデータを実際に確認し、脅威インテリジェンスを使用した 機械学習 や、分析 ユースケース を使用したさまざまな手段も実行する。 Amazon Detectiveは馴染みのない方もいるかもしれないが、主にGuardDutyの検出結果を調査するのに役立つサービス。 Amazon Detectiveはバックエンドにグラフデータベースを利用しており、リソースと環境間の関係を作成する。 MITRE ATT&CKのような攻撃 フレームワーク に基づいて調査結果をグループ化し、要約を表示する機能をリリースした( Amazon Detective finding group summaries )。我々はこの機能をいち早く提供したかった。 Amazon Inspectorはソフトウェアの 脆弱性 管理にフォーカスしたサービス。 発表されたLambdaコードスキャンでは、コードの 脆弱性 を見つけ、修正方針、もしくは修正方針を盛り込んだ新たなコードが表示されるようになった。 AWS GenAI Chatbot を使用することで、例えば現在のsecurity findingsに適用するための自環境でのIAM戦略であったり、セキュリティ対策の優先度を教えてくれる。 Amazon Qはマネージドサービスであり、カスタマイズができない。インシデントレスポンスでは AWS GenAI Chatbotが選択肢となる。 最後にしっかりre:Inforceを宣伝する。 感想 今回、セキュリティ系サービスの中でも特にDetectiveのアップデートは多かったと思います。 ただし、Detectiveを有効活用している事例をあまり聞かないので、まだ浸透はしておらず、これから来るんだろうなといった印象を受けました。 また、インシデント対応における生成AIの活用については、発表のあった Amazon Qではなく、 AWS GenAI Chatbotを活用するという点は発見でした。初見だったため一度試してみようかなと思います。 さて、今回参加してみたChalk Talk ですが、スピーカーが話している最中に、質問がバンバン飛び交うようなセッションは、日本ではあまり体験できないんじゃないかと思い、刺激を受けました。あのバイタリティを見習いたいものです。 現地に行かれる場合はぜひ参加してみるといいと思います! 最後に 今年は生成AIが大きなテーマとなった印象を受け、セキュリティにも生成AI活用の波がきていることを身をもって感じました。 また、同じセキュリティ関連のセッションに、業務でセキュリティに携わっている日本人の方も参加されており、セッション後にコミュニケーションを取ることができたことも収穫の1つでした。 来年も現地に行けるといいなあ〜。と余韻に浸りながら、今年の締め括りにしたいと思います。 最後まで読んでいただき、ありがとうございました! 執筆: @fukuyama.kenta 、レビュー: @yamashita.tsuyoshi ( Shodo で執筆されました )
どーもー!X イノベーション 本部 ソフトウェアデザインセンター セキュリティグループの福山です。 本記事は 電通国際情報サービス Advent Calendar 2023 6日目の記事となります。 念願だった AWS re:Invent現地参戦、ついに実現しました! 本レポートでは、セキュリティ関連のセッションに絞って紹介したいと思います。 re:Inventとは セッション内容 Builders' Session セッション名:Patch it up: Building a vulnerability management solution 感想 Chalk Talk セッション名:How to automate incident response with AWS security services & AI/ML 感想 最後に re:Inventとは 年に一度米国ラスベガスで開催される、 AWS 主催のIT業界最大規模のイベントです。 今年は日本から1000人以上、全体の参加者は約4〜5万人とのことで、規模の大きさがわかるかと思います。 re:Invent自体は2000以上のセッションが用意されているのと、 AWS やスポンサーと交流できるEXPOが主な内容です。 セッション内容 Builders' Session Builders' Sessionとは、少人数のグループで実際に手を動かしながら学んでいくタイプのセッションで、所要時間は1時間程度です。 各テーブルに AWS エキスパートがついており、気軽に質問できるのが特徴です。 参加したBuilders' Sessionのうち、1つ紹介します。 セッション名:Patch it up: Building a vulnerability management solution セッション概要: With thousands of new common vulnerabilities and exposures discovered every month, organizations can find it challenging to keep on top of their security using traditional, on-premises patching solutions. And the shift to containers and serverless can seem complex in an already diverse IT environment. Join this builders’ session to take a deep dive into patch management across a hybrid landscape with scenarios played out for containers, serverless, and virtual machines using AWS services. You must bring your laptop to participate. 複数タイプのリソースを 脆弱性 管理する方法を学ぶ。 Cloud9上でCDKの実行環境を構築して実行し、下図のような 脆弱性 管理の仕組みを構築していく。 ここでの 脆弱性 管理というのは、パッケージの 脆弱性 、コードの 脆弱性 、ネットワーク構成の 脆弱性 を指している。 リソース別に、EC2、ECR、Lambda、ネットワークは Amazon Inspectorで検出し、オンプレサーバは AWS Systems Manager Patch Managerで検出する。それらのFindingsをSecurity Hubに集約する。 Amazon Inspectorは検知までとなるが、 AWS Systems Manager Patch Managerは検知後のパッチ適用まで自動化することも可能。 感想 複数種類のリソースの 脆弱性 管理をするのは大変ですが、オンプレサーバ+ AWS リソースに限れば、Inspector、Patch Manager、Security Hubでここまでカバーできるんだと知りました。 しかもこれらをCloud9で構築できるから素晴らしいですね。 なお、Patch Mangerによるパッチ適用の自動化に関しては、いきなり本番で実行するのではなく、検証環境を用意して一度試してみた方がよさそうです。 あとは思いつき(要望)ですが、ソフトウェア名とバージョンを手動入力すると CPE (Common Platform Enumeration)が登録され、Inspector等でスキャンができるような機能があれば、管理の幅がさらに広がって最高なんだけどなぁ〜と思ったりしました。 さて、今回参加してみたBuilders' Sessionですが、それとは別で予約がすぐ埋まる人気セッションタイプの一つにWorkshopというものがあります。 WorkshopはBuilders' Sessionの長時間コースという位置付けになります。 Builder's SessionやWorkshopは現地でしか体験できないものなので、ぜひやっておくべきものだと思います。 Chalk Talk Chalk Talk は対話型のセッションです。後日オンラインで視聴できるBreakout Session同様、基本は AWS 側で講演を進めていきますが、参加者側から任意のタイミングで質問できます。そのため、Breakout Sessionより参加人数が制限されています。また、オンライン視聴では参加者からの質問が音声に含まれませんので、全て聞くには現地に参加するしかありません。 参加したChalk Talk のうち、1つを紹介します。 セッション名:How to automate incident response with AWS security services & AI/ML セッション概要: In this chalk talk , explore how generative AI and machine learning can be used alongside key AWS security services to enrich security analytics and automate incident response for security teams, helping to reduce the time to respond to security incidents and improve the developer experience. 顧客から頻繁に話題にあがるのは、インシデント対応フローを自動化したいということ。 検出を高速化するために生成AIを活用している。 Amazon Bedrockは VPC エンドポイントを介してデータをプライベートに保てる。 LLMをカスタマイズしたり、組織内のさまざまな状況で独自のLLMを構築する必要がある場合には Amazon Sage Makerを使用できる。 ここにいる皆さんがよく知っているであろうGuardDuty は2000のTOP AWS カスタマーのうち90%以上が利用している。 GuardDutyはECSランタイムモニタリング、EC2ランタイムモニタリングをサポートし、さらに多くのデータソースを収集できるようになった。コン トロール プレーンのログを側面からでなく、リソース上のデータを実際に確認し、脅威インテリジェンスを使用した 機械学習 や、分析 ユースケース を使用したさまざまな手段も実行する。 Amazon Detectiveは馴染みのない方もいるかもしれないが、主にGuardDutyの検出結果を調査するのに役立つサービス。 Amazon Detectiveはバックエンドにグラフデータベースを利用しており、リソースと環境間の関係を作成する。 MITRE ATT&CKのような攻撃 フレームワーク に基づいて調査結果をグループ化し、要約を表示する機能をリリースした( Amazon Detective finding group summaries )。我々はこの機能をいち早く提供したかった。 Amazon Inspectorはソフトウェアの 脆弱性 管理にフォーカスしたサービス。 発表されたLambdaコードスキャンでは、コードの 脆弱性 を見つけ、修正方針、もしくは修正方針を盛り込んだ新たなコードが表示されるようになった。 AWS GenAI Chatbot を使用することで、例えば現在のsecurity findingsに適用するための自環境でのIAM戦略であったり、セキュリティ対策の優先度を教えてくれる。 Amazon Qはマネージドサービスであり、カスタマイズができない。インシデントレスポンスでは AWS GenAI Chatbotが選択肢となる。 最後にしっかりre:Inforceを宣伝する。 感想 今回、セキュリティ系サービスの中でも特にDetectiveのアップデートは多かったと思います。 ただし、Detectiveを有効活用している事例をあまり聞かないので、まだ浸透はしておらず、これから来るんだろうなといった印象を受けました。 また、インシデント対応における生成AIの活用については、発表のあった Amazon Qではなく、 AWS GenAI Chatbotを活用するという点は発見でした。初見だったため一度試してみようかなと思います。 さて、今回参加してみたChalk Talk ですが、スピーカーが話している最中に、質問がバンバン飛び交うようなセッションは、日本ではあまり体験できないんじゃないかと思い、刺激を受けました。あのバイタリティを見習いたいものです。 現地に行かれる場合はぜひ参加してみるといいと思います! 最後に 今年は生成AIが大きなテーマとなった印象を受け、セキュリティにも生成AI活用の波がきていることを身をもって感じました。 また、同じセキュリティ関連のセッションに、業務でセキュリティに携わっている日本人の方も参加されており、セッション後にコミュニケーションを取ることができたことも収穫の1つでした。 来年も現地に行けるといいなあ〜。と余韻に浸りながら、今年の締め括りにしたいと思います。 最後まで読んでいただき、ありがとうございました! 執筆: @fukuyama.kenta 、レビュー: @yamashita.tsuyoshi ( Shodo で執筆されました )
こんにちは。X(クロス) イノベーション 本部 クラウド イノベーション センターの柴田です。 この記事は 電通国際情報サービス Advent Calendar 2023 の5日目の投稿です。 前日の記事は宮澤さんの「Jira Automationで作成した変数のスコープについて」でした。 はじめに 入力変数の検証 概要 設定方法 検証 オブジェクトの事前条件と事後条件の検証 概要 ユースケース 設定方法 リソース、データソース 出力 検証 構築したインフラストラクチャの check による検証 概要 ユースケース 設定方法 検証 まとめ おわりに 参考 はじめに Terraformでインフラスト ラク チャを構築する際、変数やリソースが期待する条件を満たしているか検証したいケースがあると思います。 この記事では変数やオブジェクトの検証に役立つTerraformの以下の機能を紹介します。 入力変数の検証 オブジェクトの事前条件と事後条件の検証 構築したインフラスト ラク チャの check による検証 なお、この記事の内容は以下のバージョンのTerraformを前提とします。 $ terraform version Terraform v1.6.3 on linux_amd64 入力変数の検証 概要 入力変数の値が指定した条件を満たしているか validation を用いて検証します。 この機能はTerraform v0.13.0以降で利用できます。 設定方法 variable に1つ以上の validation を設定します。 中身は以下の表のとおりです。 入力変数の検証の場合 condition が参照できる変数は自身のみです。 項目 説明 condition 満たすべき条件。 true なら検証成功、 false なら検証失敗。 error_message 検証に失敗した場合に表示されるエラーメッセージ。 variable "image_id" { type = string description = "The id of the machine image (AMI) to use for the server." validation { condition = can ( regex ( "^ami-" , var.image_id)) error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"." } } 検証 planとapplyの実行時に各 variable の condition が評価されます。 condition が false になるとTerraformは error_message を含むエラーを表示して異常終了します。 $ terraform plan -var image_id=123 Planning failed. Terraform encountered an error while generating this plan. ╷ │ Error: Invalid value for variable │ │ on variables.tf line 1: │ 1: variable "image_id" { │ ├──────────────── │ │ var.image_id is "123" │ │ The image_id value must be a valid AMI id, starting with "ami-". │ │ This was checked by the validation rule at variables.tf:5,3-13. ╵ オブジェクトの事前条件と事後条件の検証 概要 各オブジェクトを評価する前後に、指定した条件を満たしているかを検証します。 事前条件は precondition 、事後条件は postcondition を使用します。 この機能はTerraform v1.2.0以降で利用できます。 ユースケース 事前条件には特定のオブジェクトを評価するために満たすべき前提条件を記述します。 事後条件には特定のオブジェクトが評価後に保証すべき条件を記述します。 設定方法 以下のオブジェクトに事前条件と事後条件を設定できます。 リソース( resource ) データソース( data ) 出力( output ) ※事前条件のみ利用可能 リソース、データソース resource または data の lifecycle に事前条件 precondition または事後条件 postcondition を設定します。 それぞれ中身は先ほどと同じです。 入力変数の検証と異なり condition は他のオブジェクトを参照できます。 resource "aws_instance" "example" { instance_type = "t3.micro" ami = data.aws_ami.example.id lifecycle { precondition { condition = data.aws_ami.example.architecture == "x86_64" error_message = "The selected AMI must be for the x86_64 architecture." } postcondition { condition = self.public_dns != "" error_message = "EC2 instance must be in a VPC that has public DNS hostnames enabled." } } } 上の例ではリソース aws_instance.example に対して以下の条件を設定しています。 リソースを作成するためにAMIの アーキテクチャ は x86_64 でなければなりません。 リソースの作成後にパブリック DNS が設定されていることを保証します。 self は評価中のオブジェクト自身を参照するオブジェクトです。事後条件でのみ利用できます。 事前条件と事後条件は count や for_each と併用できます。 出力 output に事前条件 precondition を設定します。 事後条件 postcondition は設定できません。 中身は先ほどと同じです。 output "ami_id" { value = data.aws_ami.example.id precondition { condition = data.aws_ami.example.architecture == "x86_64" error_message = "The selected AMI must be for the x86_64 architecture." } } 検証 planとapplyの実行時に各オブジェクトの事前条件 precondition と事後条件 postcondition の condition が評価されます。 各オブジェクトの検証のライフサイクルは以下のとおりです。 事前条件の検証 オブジェクトの評価 事後条件の検証 事後条件は「apply後に評価される条件」ではなく「オブジェクトの評価後に評価される条件」です。 そのためplanの実行時にも事後条件は評価されます。 condition に未確定の値が含まれる場合、その condition の評価は値が確定するまで保留されます。 特に known after apply な値を含む condition はplanの実行時には評価されません。 condition が false になると、以降の処理は中断され、Terraformは error_message を含むエラーを表示して異常終了します。 ただし作成済みのリソースは削除されません。 $ terraform plan data.aws_ami.example: Reading... data.aws_ami.example: Read complete after 0s [id=ami-0d8d9f072b1e8e8fe] Planning failed. Terraform encountered an error while generating this plan. ╷ │ Error: Resource precondition failed │ │ on condition.tf line 17, in resource "aws_instance" "example": │ 17: condition = data.aws_ami.example.architecture == "x86_64" │ ├──────────────── │ │ data.aws_ami.example.architecture is "arm64" │ │ The selected AMI must be for the x86_64 architecture. ╵ 構築したインフラスト ラク チャの check による検証 概要 planとapplyの実行の終わりに指定した条件が満たされているか check を用いて検証します。 check の検証は、これまで説明した他の検証機能と異なり、検証に失敗してもplanやapplyの実行は中断されません。 この機能はTerraform v1.5.0以降で利用できます。 ユースケース 構築したインフラスト ラク チャが指定した条件を満たしているか検証します。 check は事後条件と似ていますが 特定のオブジェクトではなくインフラスト ラク チャ全体を検証したい場合 検証に失敗した際にエラーを発生させて処理を中断したくない場合 には事後条件よりも check を使うとよいでしょう。 設定方法 0〜1個のデータソース 1個以上の assert を含む check を設定します。 check 内のデータソースはスコープ付きデータソースと呼ばれ、以下の特徴があります。 check の外側からは参照できません。 for_each や count との併用はできません。 assert の中身は先ほどと同じです。 check "health_check" { data "http" "alb" { url = "https://$ { aws_lb.example.dns_name } " } assert { condition = data.http.alb.status_code == 200 error_message = "$ { data.http.alb.url } returned an unhealthy status code" } } 検証 planとapplyの実行の終わりに condition が評価されます。 事前条件や事後条件と同じく known after apply な値に依存する condition はplanの実行時には評価されません。 インフラスト ラク チャがまだ構築されていないplan時に check を評価したくない場合は、リソースが実際に作成された後にスコープ付きデータソースおよび condition が評価されるよう、スコープ付きデータソースからリソースへの依存関係を depends_on などを使って設定するとよいでしょう。 condition が false になった場合、またはスコープ付きデータソースのproviderでエラーが発生した場合、Terraformは error_message を含む警告を表示して処理を継続します。 $ terraform plan # (中略) ╷ │ Warning: Error making request │ │ with data.http.alb, │ on main.tf line 14, in check "health_check": │ 14: data "http" "alb" { │ │ Error making request: GET https://example.com.invalid giving up after 1 attempt(s): Get "https://example.com.invalid": dial tcp: lookup example.com.invalid on 127.0.0.53:53: no such host ╵ まとめ 以下の表はここまでの内容をまとめたものです。 主な ユースケース 記述箇所 検証されるタイミング count , for_each の併用 condition が false になった場合の挙動 入力変数の検証 入力変数の検証 variable variable の評価前 不可 異常終了 オブジェクトの事前条件の検証 特定のオブジェクトを評価するために満たすべき前提条件の検証 resource , data , output 各オブジェクトの評価前 可 異常終了。作成済みのリソースは削除されない。 オブジェクトの事後条件の検証 特定のオブジェクトが評価後に保証すべき条件の検証 resource , data 各オブジェクトの評価後 可 異常終了。作成済みのリソースは削除されない。 構築したインフラスト ラク チャの check による検証 構築したインフラスト ラク チャの検証 check (スコープ付きデータソースを利用) planとapplyの終わり 不可 警告を表示して処理を継続する おわりに この記事ではTerraformの変数やオブジェクトが期待する条件を満たしているか検証する方法として以下の機能を紹介しました。 入力変数の検証 オブジェクトの事前条件と事後条件の検証 構築したインフラスト ラク チャの check による検証 他にもTerraform v1.6で Tests の機能が導入されるなど、最近はTerraformの検証・テストに関する機能がどんどん充実していると感じます。 これらの機能を活用してより安全にインフラスト ラク チャを構築したいですね。 ここまで読んでいただきありがとうございました。 参考 Custom Conditions - Configuration Language | Terraform | HashiCorp Developer Checks - Configuration Language | Terraform | HashiCorp Developer 私たちは一緒に働いてくれる仲間を募集しています! クラウドアーキテクト 執筆: @shibata.takao 、レビュー: @fukutake.hiroaki ( Shodo で執筆されました )
こんにちは。X(クロス) イノベーション 本部 クラウド イノベーション センターの柴田です。 この記事は 電通国際情報サービス Advent Calendar 2023 の5日目の投稿です。 前日の記事は宮澤さんの「Jira Automationで作成した変数のスコープについて」でした。 はじめに 入力変数の検証 概要 設定方法 検証 オブジェクトの事前条件と事後条件の検証 概要 ユースケース 設定方法 リソース、データソース 出力 検証 構築したインフラストラクチャの check による検証 概要 ユースケース 設定方法 検証 まとめ おわりに 参考 はじめに Terraformでインフラスト ラク チャを構築する際、変数やリソースが期待する条件を満たしているか検証したいケースがあると思います。 この記事では変数やオブジェクトの検証に役立つTerraformの以下の機能を紹介します。 入力変数の検証 オブジェクトの事前条件と事後条件の検証 構築したインフラスト ラク チャの check による検証 なお、この記事の内容は以下のバージョンのTerraformを前提とします。 $ terraform version Terraform v1.6.3 on linux_amd64 入力変数の検証 概要 入力変数の値が指定した条件を満たしているか validation を用いて検証します。 この機能はTerraform v0.13.0以降で利用できます。 設定方法 variable に1つ以上の validation を設定します。 中身は以下の表のとおりです。 入力変数の検証の場合 condition が参照できる変数は自身のみです。 項目 説明 condition 満たすべき条件。 true なら検証成功、 false なら検証失敗。 error_message 検証に失敗した場合に表示されるエラーメッセージ。 variable "image_id" { type = string description = "The id of the machine image (AMI) to use for the server." validation { condition = can ( regex ( "^ami-" , var.image_id)) error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"." } } 検証 planとapplyの実行時に各 variable の condition が評価されます。 condition が false になるとTerraformは error_message を含むエラーを表示して異常終了します。 $ terraform plan -var image_id=123 Planning failed. Terraform encountered an error while generating this plan. ╷ │ Error: Invalid value for variable │ │ on variables.tf line 1: │ 1: variable "image_id" { │ ├──────────────── │ │ var.image_id is "123" │ │ The image_id value must be a valid AMI id, starting with "ami-". │ │ This was checked by the validation rule at variables.tf:5,3-13. ╵ オブジェクトの事前条件と事後条件の検証 概要 各オブジェクトを評価する前後に、指定した条件を満たしているかを検証します。 事前条件は precondition 、事後条件は postcondition を使用します。 この機能はTerraform v1.2.0以降で利用できます。 ユースケース 事前条件には特定のオブジェクトを評価するために満たすべき前提条件を記述します。 事後条件には特定のオブジェクトが評価後に保証すべき条件を記述します。 設定方法 以下のオブジェクトに事前条件と事後条件を設定できます。 リソース( resource ) データソース( data ) 出力( output ) ※事前条件のみ利用可能 リソース、データソース resource または data の lifecycle に事前条件 precondition または事後条件 postcondition を設定します。 それぞれ中身は先ほどと同じです。 入力変数の検証と異なり condition は他のオブジェクトを参照できます。 resource "aws_instance" "example" { instance_type = "t3.micro" ami = data.aws_ami.example.id lifecycle { precondition { condition = data.aws_ami.example.architecture == "x86_64" error_message = "The selected AMI must be for the x86_64 architecture." } postcondition { condition = self.public_dns != "" error_message = "EC2 instance must be in a VPC that has public DNS hostnames enabled." } } } 上の例ではリソース aws_instance.example に対して以下の条件を設定しています。 リソースを作成するためにAMIの アーキテクチャ は x86_64 でなければなりません。 リソースの作成後にパブリック DNS が設定されていることを保証します。 self は評価中のオブジェクト自身を参照するオブジェクトです。事後条件でのみ利用できます。 事前条件と事後条件は count や for_each と併用できます。 出力 output に事前条件 precondition を設定します。 事後条件 postcondition は設定できません。 中身は先ほどと同じです。 output "ami_id" { value = data.aws_ami.example.id precondition { condition = data.aws_ami.example.architecture == "x86_64" error_message = "The selected AMI must be for the x86_64 architecture." } } 検証 planとapplyの実行時に各オブジェクトの事前条件 precondition と事後条件 postcondition の condition が評価されます。 各オブジェクトの検証のライフサイクルは以下のとおりです。 事前条件の検証 オブジェクトの評価 事後条件の検証 事後条件は「apply後に評価される条件」ではなく「オブジェクトの評価後に評価される条件」です。 そのためplanの実行時にも事後条件は評価されます。 condition に未確定の値が含まれる場合、その condition の評価は値が確定するまで保留されます。 特に known after apply な値を含む condition はplanの実行時には評価されません。 condition が false になると、以降の処理は中断され、Terraformは error_message を含むエラーを表示して異常終了します。 ただし作成済みのリソースは削除されません。 $ terraform plan data.aws_ami.example: Reading... data.aws_ami.example: Read complete after 0s [id=ami-0d8d9f072b1e8e8fe] Planning failed. Terraform encountered an error while generating this plan. ╷ │ Error: Resource precondition failed │ │ on condition.tf line 17, in resource "aws_instance" "example": │ 17: condition = data.aws_ami.example.architecture == "x86_64" │ ├──────────────── │ │ data.aws_ami.example.architecture is "arm64" │ │ The selected AMI must be for the x86_64 architecture. ╵ 構築したインフラスト ラク チャの check による検証 概要 planとapplyの実行の終わりに指定した条件が満たされているか check を用いて検証します。 check の検証は、これまで説明した他の検証機能と異なり、検証に失敗してもplanやapplyの実行は中断されません。 この機能はTerraform v1.5.0以降で利用できます。 ユースケース 構築したインフラスト ラク チャが指定した条件を満たしているか検証します。 check は事後条件と似ていますが 特定のオブジェクトではなくインフラスト ラク チャ全体を検証したい場合 検証に失敗した際にエラーを発生させて処理を中断したくない場合 には事後条件よりも check を使うとよいでしょう。 設定方法 0〜1個のデータソース 1個以上の assert を含む check を設定します。 check 内のデータソースはスコープ付きデータソースと呼ばれ、以下の特徴があります。 check の外側からは参照できません。 for_each や count との併用はできません。 assert の中身は先ほどと同じです。 check "health_check" { data "http" "alb" { url = "https://$ { aws_lb.example.dns_name } " } assert { condition = data.http.alb.status_code == 200 error_message = "$ { data.http.alb.url } returned an unhealthy status code" } } 検証 planとapplyの実行の終わりに condition が評価されます。 事前条件や事後条件と同じく known after apply な値に依存する condition はplanの実行時には評価されません。 インフラスト ラク チャがまだ構築されていないplan時に check を評価したくない場合は、リソースが実際に作成された後にスコープ付きデータソースおよび condition が評価されるよう、スコープ付きデータソースからリソースへの依存関係を depends_on などを使って設定するとよいでしょう。 condition が false になった場合、またはスコープ付きデータソースのproviderでエラーが発生した場合、Terraformは error_message を含む警告を表示して処理を継続します。 $ terraform plan # (中略) ╷ │ Warning: Error making request │ │ with data.http.alb, │ on main.tf line 14, in check "health_check": │ 14: data "http" "alb" { │ │ Error making request: GET https://example.com.invalid giving up after 1 attempt(s): Get "https://example.com.invalid": dial tcp: lookup example.com.invalid on 127.0.0.53:53: no such host ╵ まとめ 以下の表はここまでの内容をまとめたものです。 主な ユースケース 記述箇所 検証されるタイミング count , for_each の併用 condition が false になった場合の挙動 入力変数の検証 入力変数の検証 variable variable の評価前 不可 異常終了 オブジェクトの事前条件の検証 特定のオブジェクトを評価するために満たすべき前提条件の検証 resource , data , output 各オブジェクトの評価前 可 異常終了。作成済みのリソースは削除されない。 オブジェクトの事後条件の検証 特定のオブジェクトが評価後に保証すべき条件の検証 resource , data 各オブジェクトの評価後 可 異常終了。作成済みのリソースは削除されない。 構築したインフラスト ラク チャの check による検証 構築したインフラスト ラク チャの検証 check (スコープ付きデータソースを利用) planとapplyの終わり 不可 警告を表示して処理を継続する おわりに この記事ではTerraformの変数やオブジェクトが期待する条件を満たしているか検証する方法として以下の機能を紹介しました。 入力変数の検証 オブジェクトの事前条件と事後条件の検証 構築したインフラスト ラク チャの check による検証 他にもTerraform v1.6で Tests の機能が導入されるなど、最近はTerraformの検証・テストに関する機能がどんどん充実していると感じます。 これらの機能を活用してより安全にインフラスト ラク チャを構築したいですね。 ここまで読んでいただきありがとうございました。 参考 Custom Conditions - Configuration Language | Terraform | HashiCorp Developer Checks - Configuration Language | Terraform | HashiCorp Developer 私たちは一緒に働いてくれる仲間を募集しています! クラウドアーキテクト 執筆: @shibata.takao 、レビュー: @fukutake.hiroaki ( Shodo で執筆されました )
はいどーもー! コミュニケーションIT事業部の宮澤響です! 普段は AppGuard というセキュリティ対策ソフトウェアの導入支援に携わっています! 本記事は 電通国際情報サービス Advent Calendar 2023 4日目(2日目相当)の記事です! 電通国際情報サービス Advent Calendarでは3年連続3回目の二番手(2日目相当の枠での投稿)となりますが、来年からは社名変更に伴いテックブログやAdvent Calendarの名称も変更となるため、晴れて 「 電通国際情報サービス Advent Calendar 永遠の二番手」 の称号を手に入れました。(?) なお、記念すべき1日目である先週金曜日の記事は、米谷典比古さんの「 祝 GA!Microsoft Fabric で今できることをまとめてみた 」でした! データ分析に関する統合環境を提供する SaaS である Microsoft Fabricについて分かりやすく書かれた記事ですので、ぜひご一読ください! ということで、本記事では、 Jira Automation で変数を作成、利用する際の注意点についてご紹介します! Jira Automationとは 簡単なルールを作成してみる 何が間違っているのか まとめ Jira Automationとは Jira Automationとは、Jira上の様々なワークフローを基本的にノーコードで自動化できるサービスです。 例えば、「特定の条件に一致するチケットが起票されたら担当者にメールを送信する」、「あるプロジェクトにチケットが起票されたら別のプロジェクトにも同じチケットを起票する」、といった処理を自動化できるため、Jiraによる課題管理をより効率的に実施できます。 実際、私自身も、普段の業務において、「問い合わせのチケットが起票から3日以上経過してもクローズしていない場合、Slackの指定チャネルに担当者をメンションして状況の報告依頼を投稿する」といった処理を自動化することで、問い合わせ対応の抜け漏れを防いでいます。 なお、Jira Automationは、Jira Cloudには初めから付帯していますが、Jira ServerやJira Data Centerで利用する場合には追加のアプリケーションのインストールが必要となります。( 参考 ) 概要については こちら を、利用方法については こちら を、それぞれご参照ください! 簡単なルールを作成してみる まずはサンプルとして以下のようなルールを作成してみます。 なお、ルールとは、Jira Automationによる自動化の設定の単位です。 Jira Automationの利用方法の紹介記事ではないため詳細は省略しますが、こちらのルールは以下のような内容となります。 (チケット上からの手動実行により以下の処理を開始) 実行元チケットのステータスが DONE の場合 完了! という値をもつ変数 test を作成 実行元チケットのステータスが DONE 以外の場合 未完了! という値をもつ変数 test を作成 変数 test の値を 【】 で囲んで監査ログに出力 ではここで問題です。 ステータスが DONE である以下のチケットに対してこちらのルールを実行すると、監査ログにはどのような値が出力されるでしょうか? 正解は…。 【】 のみが出力されました。 今回の実行元チケットのステータスは DONE であるため、監査ログには 【完了!】 と出力されていてほしいところですが、どうやら何かが間違っているようです。 何が間違っているのか 原因を探るべく、先ほどのルールを以下のように修正してみます。 伝家の宝刀、printf デバッグ です。 (チケット上からの手動実行により以下の処理を開始) 実行元チケットのステータスが DONE の場合 完了! という値をもつ変数 test を作成 変数 test の値を A【】 で囲んで監査ログに出力 実行元チケットのステータスが DONE 以外の場合 未完了! という値をもつ変数 test を作成 変数 test の値を B【】 で囲んで監査ログに出力 変数 test の値を C【】 で囲んで監査ログに出力 出力結果は以下のとおりです。 A の監査ログには 【完了!】 と出力されたのに対し、 C の監査ログには 【】 のみが出力されました。 どうやら、条件分岐の中でしか変数の値が出力されないようです。 ここで気づいたのですが、Jira Automationの変数にも、一般的な プログラミング言語 と同じように、 スコープの概念がある のではないでしょうか。 (スコープ:変数がどこから参照できるかを定めた変数の有効範囲) そして、 変数を作成 という項目名ではあるものの、実際には変数への代入を行っているのではないでしょうか。 であれば、以下のように条件分岐の外側で変数を宣言しておけば、期待どおりの結果が得られそうです。 (チケット上からの手動実行により以下の処理を開始) 初期値! という値をもつ変数 test を作成 実行元チケットのステータスが DONE の場合 完了! という値をもつ変数 test を作成 実行元チケットのステータスが DONE 以外の場合 未完了! という値をもつ変数 test を作成 変数 test の値を 【】 で囲んで監査ログに出力 無事に監査ログに 【完了!】 と出力されました! やはり、Jira Automationの変数にも、一般的な プログラミング言語 と同じように、スコープの概念があるようです。 つまり、今回の例で言えば、 条件分岐の外で作成した変数の値は条件分岐の中からも参照できるが、条件分岐の中で作成した変数の値は条件分岐の外からは参照できない ということです。 最初に例として挙げたルールでは、条件分岐の中( 完了! や 未完了! の部分)で作成した変数を条件分岐の外(監査ログに値を出力する部分)で参照しようとしていたため、正しい出力が得られませんでした。 一方、先ほどのルールでは、あらかじめ条件分岐の外( 初期値! の部分)で変数を作成していたため、監査ログに値を出力する部分でも変数の値を参照でき、正しい出力が得られた、ということになります。 なお、上記の内容は2023年10月末時点では公式ドキュメント( 日本語 / 英語 )に記載がありませんので、プログラミング未経験の方がJira Automationの 変数の作成 を利用する際には、ちょっとした落とし穴になってしまうのではないかと感じました。 まとめ 本記事では、Jira Automationの変数にも、一般的な プログラミング言語 と同じように、スコープの概念があることを検証しました。 Jira Automationを利用される際は、変数のスコープに注意して利用されるとよいのではないかと思います。 電通国際情報サービス Advent Calendar 2023 5日目(3日目相当)となる明日の記事は、柴田崇夫さんの「 TerraformのCustom ConditionsとChecksの紹介 」です! お楽しみに! 最後までお読みいただき、本当にありがとうございました! 私たちは同じ事業部で共に働いていただける仲間を募集しています! みなさまのご応募、お待ちしています! クラウドアーキテクト アプリケーションアーキテクト 電通グループ向け基幹システムプロジェクトマネージャ 戦略的IT プロジェクトマネージャ/ITコンサルタント 執筆: @miyazawa.hibiki 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
はいどーもー! コミュニケーションIT事業部の宮澤響です! 普段は AppGuard というセキュリティ対策ソフトウェアの導入支援に携わっています! 本記事は 電通国際情報サービス Advent Calendar 2023 4日目(2日目相当)の記事です! 電通国際情報サービス Advent Calendarでは3年連続3回目の二番手(2日目相当の枠での投稿)となりますが、来年からは社名変更に伴いテックブログやAdvent Calendarの名称も変更となるため、晴れて 「 電通国際情報サービス Advent Calendar 永遠の二番手」 の称号を手に入れました。(?) なお、記念すべき1日目である先週金曜日の記事は、米谷典比古さんの「 祝 GA!Microsoft Fabric で今できることをまとめてみた 」でした! データ分析に関する統合環境を提供する SaaS である Microsoft Fabricについて分かりやすく書かれた記事ですので、ぜひご一読ください! ということで、本記事では、 Jira Automation で変数を作成、利用する際の注意点についてご紹介します! Jira Automationとは 簡単なルールを作成してみる 何が間違っているのか おわりに Jira Automationとは Jira Automationとは、Jira上の様々なワークフローを基本的にノーコードで自動化できるサービスです。 例えば、「特定の条件に一致するチケットが起票されたら担当者にメールを送信する」、「あるプロジェクトにチケットが起票されたら別のプロジェクトにも同じチケットを起票する」、といった処理を自動化できるため、Jiraによる課題管理をより効率的に実施できます。 実際、私自身も、普段の業務において、「問い合わせのチケットが起票から3日以上経過してもクローズしていない場合、Slackの指定チャネルに担当者をメンションして状況の報告依頼を投稿する」といった処理を自動化することで、問い合わせ対応の抜け漏れを防いでいます。 なお、Jira Automationは、Jira Cloudには初めから付帯していますが、Jira ServerやJira Data Centerで利用する場合には追加のアプリケーションのインストールが必要となります。( 参考 ) 概要については こちら を、利用方法については こちら を、それぞれご参照ください! 簡単なルールを作成してみる まずはサンプルとして以下のようなルールを作成してみます。 なお、ルールとは、Jira Automationによる自動化の設定の単位です。 Jira Automationの利用方法の紹介記事ではないため詳細は省略しますが、こちらのルールは以下のような内容となります。 (チケット上からの手動実行により以下の処理を開始) 実行元チケットのステータスが DONE の場合 完了! という値をもつ変数 test を作成 実行元チケットのステータスが DONE 以外の場合 未完了! という値をもつ変数 test を作成 変数 test の値を 【】 で囲んで監査ログに出力 ではここで問題です。 ステータスが DONE である以下のチケットに対してこちらのルールを実行すると、監査ログにはどのような値が出力されるでしょうか? 正解は…。 【】 のみが出力されました。 今回の実行元チケットのステータスは DONE であるため、監査ログには 【完了!】 と出力されていてほしいところですが、どうやら何かが間違っているようです。 何が間違っているのか 原因を探るべく、先ほどのルールを以下のように修正してみます。 伝家の宝刀、printf デバッグ です。 (チケット上からの手動実行により以下の処理を開始) 実行元チケットのステータスが DONE の場合 完了! という値をもつ変数 test を作成 変数 test の値を A【】 で囲んで監査ログに出力 実行元チケットのステータスが DONE 以外の場合 未完了! という値をもつ変数 test を作成 変数 test の値を B【】 で囲んで監査ログに出力 変数 test の値を C【】 で囲んで監査ログに出力 出力結果は以下のとおりです。 A の監査ログには 【完了!】 と出力されたのに対し、 C の監査ログには 【】 のみが出力されました。 どうやら、条件分岐の中でしか変数の値が出力されないようです。 ここで気づいたのですが、Jira Automationの変数にも、一般的な プログラミング言語 と同じように、 スコープの概念がある のではないでしょうか。 (スコープ:変数がどこから参照できるかを定めた変数の有効範囲) そして、 変数を作成 という項目名ではあるものの、実際には変数への代入を行っているのではないでしょうか。 であれば、以下のように条件分岐の外側で変数を宣言しておけば、期待どおりの結果が得られそうです。 (チケット上からの手動実行により以下の処理を開始) 初期値! という値をもつ変数 test を作成 実行元チケットのステータスが DONE の場合 完了! という値をもつ変数 test を作成 実行元チケットのステータスが DONE 以外の場合 未完了! という値をもつ変数 test を作成 変数 test の値を 【】 で囲んで監査ログに出力 無事に監査ログに 【完了!】 と出力されました! やはり、Jira Automationの変数にも、一般的な プログラミング言語 と同じように、スコープの概念があるようです。 つまり、今回の例で言えば、 条件分岐の外で作成した変数の値は条件分岐の中からも参照できるが、条件分岐の中で作成した変数の値は条件分岐の外からは参照できない ということです。 最初に例として挙げたルールでは、条件分岐の中( 完了! や 未完了! の部分)で作成した変数を条件分岐の外(監査ログに値を出力する部分)で参照しようとしていたため、正しい出力が得られませんでした。 一方、先ほどのルールでは、あらかじめ条件分岐の外( 初期値! の部分)で変数を作成していたため、監査ログに値を出力する部分でも変数の値を参照でき、正しい出力が得られた、ということになります。 なお、上記の内容は2023年10月末時点では公式ドキュメント( 日本語 / 英語 )に記載がありませんので、プログラミング未経験の方がJira Automationの 変数の作成 を利用する際には、ちょっとした落とし穴になってしまうのではないかと感じました。 おわりに 本記事では、Jira Automationの変数にも、一般的な プログラミング言語 と同じように、スコープの概念があることを検証しました。 Jira Automationを利用される際は、変数のスコープに注意して利用されるとよいのではないかと思います。 電通国際情報サービス Advent Calendar 2023 5日目(3日目相当)となる明日の記事は、柴田崇夫さんの「 TerraformのCustom ConditionsとChecksの紹介 」です! お楽しみに! 最後までお読みいただき、本当にありがとうございました! 私たちは同じ事業部で共に働いていただける仲間を募集しています! みなさまのご応募、お待ちしています! <電通×IT>電通グループ基幹システムプロジェクトマネージャー エンタープライズ向けDX推進リーダー/エンジニア <電通×IT>クラウドアーキテクト <電通×IT>アプリケーションアーキテクト 製品・プラットフォーム開発エンジニア 執筆: @miyazawa.hibiki 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
XI 本部  クラウド イノベーション センターの米谷です。本記事は 電通国際情報サービス Advent Calendar 2023 の 1 日目の投稿です。今年の アドベントカレンダー の栄えあるトップバッターを務めさせていただきます。よろしくお願いします。 先日実施された Microsoft の年次テクニカルカンファレンス Ignite にて Microsoft Fabric の GA が発表されました! Microsoft Fabric は Microsoft のデータ関連製品として SQL Server 以来最も インパク トのある製品と言われており、 Ignite の基調講演の中でも取り上げられるなど注目を集めています。 Microsoft Fabric には様々な機能があり GA のタイミングで新しい発表も多くあったため、本稿ではそれらの情報を整理し Microsoft Fabric の特徴や魅力を改めて確認していきたいと思います。 はじめに データ分析基盤を取り巻く課題 Microsoft Fabric のコンセプト OneLake Data Factory Synapse Data Engineering Synapse Data Science Synapse Data Warehouse Synapse Real-Time Analytics Power BI Data Activator Purview まとめ はじめに データ分析基盤を取り巻く課題 機能紹介の前に Microsoft Fabric が登場するに至った背景をおさらいしておきたいと思います。データ分析基盤の構成要素はデータレイク、ETL、データウェアハウス、BI など多岐に渡りそれぞれに適したツールがあります。例えば Microsoft の Azure や Microsoft 365 では以下のようなサービスが提供されています。 データレイク : Azure Data Lake Storage Gen2 ETL : Azure Data Factory データウェアハウス : Azure Syanapse Analytics(専用 SQL プール) BI : Microsoft Power BI データカタログ、データガバナンス : Microsoft Purview これらを適切に組み合わせることではじめてデータ分析基盤ができあがります。Azure の場合上記のサービスは PaaS として提供されており比較的容易に構築できますが、それでも相応に労力の割かれる作業となることは事実であり、データを分析するためのスタートラインに立つまでにやることが多いというのが悩みの種となります。 Microsoft Fabric のコンセプト このような背景の中で発表された Microsoft Fabric は、上述の課題解決を狙いとした以下に示す 4 つのコンセプトを持ちます。 オールインワンの SaaS として提供 レイクセントリックな アーキテクチャ ー あらゆるロールのビジネスユーザーを支援 AI(Copilot) 実装 Microsoft Fabric には DWH、ETL、BI といったデータ分析に必要な機能が全て含まれた形で SaaS として提供されているため、ユーザーは導入後すぐにこれらの機能を使いデータ分析を行うことができます。分析に必要なデータは OneLake と呼ばれる場所で集約・管理され、使う機能によってデータを重複管理する必要はありません。データ分析には様々な役割のユーザーが関わりますが、皆が Microsoft Fabricという一つのサービスでコラボレーションできます。搭載されたAI 機能により、分析作業の質やスピードの向上が期待されます。 以降、各機能紹介の中でこれらのコンセプトがどのように組み込まれているかを都度解説します。 OneLake いよいよここから Microsoft Fabric の各機能の紹介に移っていきます。初めに紹介するのは、上述のレイクセントリックな アーキテクチャ ーで中心的な役割を果たす OneLake です。個人のデータ管理のために使用される OneDrive と対比する形で、組織のデータ分析に使用される場所という意味で OneLake という名称が付けられました。OneLake では Azure Data Lake Storage Gen2 ベースのオブジェクトストレージに分析データが Delta-Parquet 形式で保管されます。オープンスタンダードな形式である Delta-Parquet を用いることで、各機能の API が同一のデータに対してアクセス・分析可能になります。 実際に使用するに当たっては、分析対象となるデータをどのように OneLake に持ってくるか?という取り込みにかかるコストが重要になります。この点における解決策として OneLake ではショートカットと ミラーリング という 2 つの機能を提供しています。ショートカットとは ファイルシステム の シンボリックリンク のようなイメージで、データの実体は取り込み元にあるままで Microsoft Fabric で取り扱えるようにする仕組みです。データを移動させることなく分析ができるという非常に強力な機能となっています。一方の ミラーリング は取り込み元のデータをシームレスに OneLake にコピーする仕組みとなっており、データの取り込み作業の簡略化が期待できます。 現時点でショートカットは Azure Data Lake Storage Gen2 や Amazon S3 、Dataverse が、 ミラーリング は Azure SQL Database や Snowflake 、Azure CosmosDB などがそれぞれ対応しています。今後もショートカットにはオブジェクトストレージ系のサービスが、 ミラーリング にはデータベースや NoSQL 系のサービスが追加されていくのではと予想されます。 Data Factory Microsoft Fabric で ETL の役割を果たすのが Data Factory です。Azure Data Factory と同様に 100 を超えるコネクタを有し、オンプレミスや/ クラウド を問わず様々な場所のデータを Microsoft Fabric と連携させることが可能です。 GUI による処理の定義/パイプライン実行/ログの確認が可能となっており、Dataflow Gen2 という新しいエクス ペリエ ンスの提供に加え、Copilot for Data Factory もパブリックプレビューとなり AI アシスタントを活用したフロー開発が順次利用可能となる予定となっています。 また、GA のタイミングで Virtual Net Data Gateway がパブリックプレビューとなりました。これにより Azure 環境内にある分析データと Microsoft Fabric の通信をよりセキュアに実現できるようになるため、データ連携の選択肢の一つとしての活用が期待されます。 Synapse Data Engineering 大量のデータを変換しレイクハウス アーキテクチャ を構築するデータエンジニアを支援するための機能が Synapse Data Engineering です。Synapse Data Engineering によってデータエンジニアは Notebook を用いた Spark 実行環境を利用可能となります。 現時点で Synapse Data Engineering のランタイムには Spark 3.4、Delta 2.4、 Java 11、 Python 3.10 が含まれており、今後の最新バージョンへの追従は Microsoft Fabric で管理・対応されます。また、ノートブックとレイクハウスの Git 統合、Environment アーティファクト による構成管理、 VS Code 拡張機能 などがパブリックプレビューとなっており、データエンジニア向けの開発環境が順次拡充されていることが伺えます。 Synapse Data Engineering においても Copilot がパブリックプレビューとなっています。これにより Notebook 上で AI と対話しながら任意のコードを記述・実行していくようなことがまもなく実現可能となります。 Synapse Data Science ビジネスにおける洞察・予測のためのデータサイエンス実行管理機能が Synapse Data Science です。データの探索から始まり前処理、モデル作成とその管理までデータサイエンスに必要な機能が網羅的に提供されます。 今回の GA に合わせて Synapse ML 1.0 がリリースされています。これは大規模な 機械学習 のアプリケーションを簡素化する Spark 用の オープンソース ML ライブラリで、MLFlow に加え Azure AI Search でのベクトル検索や Azure Open AI Service 統合のための API などが含まれます。 Synapse Data Engineering の項で述べた Notebook の Copilot は Synapse Data Science でも同様に提供予定となっており、データサイエンス領域における AI 活用を促進する機能がそろった環境といえるかと思います。 Synapse Data Warehouse Microsoft Fabric ではオープン データ形式 をネイティブにサポートする次世代のデータウェアハウスとして Synapse Data Warehouse が提供されます。オープン データ形式 とは OneLake の項で述べた Delta-Parquet 形式のことであり、OneLake 上で管理される Parquet ファイルに対して SQL の API を発行し分析を行うというのが大まかな処理のイメージとなります。 Synapse Data Warehouse についてはパブリックプレビュー後も継続的に機能強化が行われていましたが、今回の GA のタイミングでもいくつか新しい発表がありました。一例をあげると SQLPackage や REST API による プログラマブル な開発のサポート、Query Insights によるソリューション監視、 SQL 動的データ マスキング ( DDM ) を使用したアプリケーションの保護などです。前述の ミラーリング の機能についても、データベースが主対象になりそうなことを踏まえると Synapse Data Warehouse との親和性が高い機能に見えています。 Synapse Real-Time Analytics 昨今の分析に必要なデータは多種多様となっており、IoT デ バイス や API からのリアルタイムデータも例外ではありません。Synapse Real-Time Analytics はログ、イベント、テレメトリといったリアルタイムデータを分析するためのサービスです。 Synapse Real-Time Analytics においてもレイクセントリックな思想は受け継がれており、データが OneLake 上で管理されることに変わりはありません。また、OneLake ショートカットとして Azure Data Explorer のソースデータベースを設定できるため、既存の Azure Data Explorer 環境に対しての KQL 発行といったこれまで Azure 上で実施していた分析エクス ペリエ ンスが Microsoft Fabric 上でも実現可能となっています。 Synapse Real-Time Analytics を理解するうえで重要な要素がイベントストリームです。これは受信したリアルタイムイベントをシームレスに取り込みキャプチャ・変換した後に Microsoft Fabric のさまざまな宛先にルーティングするという、データの中継役を果たします。ソース・宛先ともに複数の形式をサポートしており、リアルタイムデータの分析をする上では欠かせない仕組みといえます。 Power BI Microsoft が長年にわたり提供してきた Power BI が、今回 Microsoft Fabric に統合されました。現在 Power BI をお使いのユーザーは適切なライセンスを割り当てることで自身の環境で Microsoft Fabric の機能を使っていくことが可能になります。 Power BI に関してはパブリックプレビュー公開当初から魅力的な機能が追加されていきました。その一つが Direct Lake モードです。従来の Direct Query モードとインポートモードの長所を掛け合わせた、リアルタイムかつ高速なレポート表示を実現した機能で、今後のレポート開発で標準となっていくことが期待されます。 Power BI Desktop の開発モードで Git 統合がサポートされレポートおよびセマンティックモデル(従来のデー タセット )のバージョン管理が可能となったのも嬉しいアップデートです。現在対応する Git リポジトリ は Azure DevOps のみですが、今後 GitHub への対応がなされていくとより利用の幅が広がってくると思われます。 Data Activator これまで紹介してきた機能は Azure や M365 で類似のサービスが存在していましたが、この項で紹介する Data Activator は Microsoft Fabric で新しく登場した機能です。データ分析においては得られた洞察から何かしらのアクションを起こしていくわけですが、それを人手で実施するのは限界があるため自動化の仕組みが必要となります。 Data Activator はそのようなニーズに応える機能となっており、特定のルールに基づく分析結果をトリガーとしてその後のアクションを実行するまでをノーコードで実装できます。使用例としては、来月の在庫予測が しきい値 を下回りそうな分析結果が出たため Teams で関係者に通知するとともに後続のアクション実行のための API を呼びだすといった処理などが考えられます。 イベントの検知箇所として現在対応しているのは Power BI のセマンティックモデルと Synapse Real-Time Analytics のイベントストリームの 2 か所となっており活用の場面が限られますが、今後拡充されて利用シナリオが広がっていくことを期待したいです。 Purview Power BI と同様に Microsoft Purview も Microsoft Fabric に統合されました。これによって提供されるようになるのが Purview ハブで、これまでデータカタログと監査で分かれていた UI の入り口が一つに統一されます。 Microsoft Fabric 上のアイテムに対してデータカタログおよび監査機能が適用されることとなり、 Microsoft Fabric にデータを集めることで自然にデータガバナンスが向上する仕組みとしていくことも可能といえます。 まとめ 各機能の紹介としては以上となります。ここまで読んでいただくだけでも非常に多くの機能の集合体であることがお分かりいただけたかと思います。個々の機能において紹介しきれていない発表などもたくさんありますので、気になる方は Microsoft の公式ドキュメントやブログもぜひチェックしてみてください。以下にリンクをまとめておきます。 Microsoft Fabric のドキュメント Prepare your data for AI innovation with Microsoft Fabric—now generally available(MSの公式ブログ) Fabric workloads are now generally available!(MSの公式ブログ) 最後までお読みいただきありがとうございました。 アドベントカレンダー は本日から始まり今月いっぱい続いていきます。明日以降も面白い記事が目白押しですので、ぜひご覧ください。 私たちは一緒に働いてくれる仲間を募集しています! クラウドアーキテクト 執筆: @yoneya.fumihiko 、レビュー: @yamashita.tsuyoshi ( Shodo で執筆されました )
XI 本部  クラウド イノベーション センターの米谷です。本記事は 電通国際情報サービス Advent Calendar 2023 の 1 日目の投稿です。今年の アドベントカレンダー の栄えあるトップバッターを務めさせていただきます。よろしくお願いします。 先日実施された Microsoft の年次テクニカルカンファレンス Ignite にて Microsoft Fabric の GA が発表されました! Microsoft Fabric は Microsoft のデータ関連製品として SQL Server 以来最も インパク トのある製品と言われており、 Ignite の基調講演の中でも取り上げられるなど注目を集めています。 Microsoft Fabric には様々な機能があり GA のタイミングで新しい発表も多くあったため、本稿ではそれらの情報を整理し Microsoft Fabric の特徴や魅力を改めて確認していきたいと思います。 はじめに データ分析基盤を取り巻く課題 Microsoft Fabric のコンセプト OneLake Data Factory Synapse Data Engineering Synapse Data Science Synapse Data Warehouse Synapse Real-Time Analytics Power BI Data Activator Purview まとめ はじめに データ分析基盤を取り巻く課題 機能紹介の前に Microsoft Fabric が登場するに至った背景をおさらいしておきたいと思います。データ分析基盤の構成要素はデータレイク、ETL、データウェアハウス、BI など多岐に渡りそれぞれに適したツールがあります。例えば Microsoft の Azure や Microsoft 365 では以下のようなサービスが提供されています。 データレイク : Azure Data Lake Storage Gen2 ETL : Azure Data Factory データウェアハウス : Azure Syanapse Analytics(専用 SQL プール) BI : Microsoft Power BI データカタログ、データガバナンス : Microsoft Purview これらを適切に組み合わせることではじめてデータ分析基盤ができあがります。Azure の場合上記のサービスは PaaS として提供されており比較的容易に構築できますが、それでも相応に労力の割かれる作業となることは事実であり、データを分析するためのスタートラインに立つまでにやることが多いというのが悩みの種となります。 Microsoft Fabric のコンセプト このような背景の中で発表された Microsoft Fabric は、上述の課題解決を狙いとした以下に示す 4 つのコンセプトを持ちます。 オールインワンの SaaS として提供 レイクセントリックな アーキテクチャ ー あらゆるロールのビジネスユーザーを支援 AI(Copilot) 実装 Microsoft Fabric には DWH、ETL、BI といったデータ分析に必要な機能が全て含まれた形で SaaS として提供されているため、ユーザーは導入後すぐにこれらの機能を使いデータ分析を行うことができます。分析に必要なデータは OneLake と呼ばれる場所で集約・管理され、使う機能によってデータを重複管理する必要はありません。データ分析には様々な役割のユーザーが関わりますが、皆が Microsoft Fabricという一つのサービスでコラボレーションできます。搭載されたAI 機能により、分析作業の質やスピードの向上が期待されます。 以降、各機能紹介の中でこれらのコンセプトがどのように組み込まれているかを都度解説します。 OneLake いよいよここから Microsoft Fabric の各機能の紹介に移っていきます。初めに紹介するのは、上述のレイクセントリックな アーキテクチャ ーで中心的な役割を果たす OneLake です。個人のデータ管理のために使用される OneDrive と対比する形で、組織のデータ分析に使用される場所という意味で OneLake という名称が付けられました。OneLake では Azure Data Lake Storage Gen2 ベースのオブジェクトストレージに分析データが Delta-Parquet 形式で保管されます。オープンスタンダードな形式である Delta-Parquet を用いることで、各機能の API が同一のデータに対してアクセス・分析可能になります。 実際に使用するに当たっては、分析対象となるデータをどのように OneLake に持ってくるか?という取り込みにかかるコストが重要になります。この点における解決策として OneLake ではショートカットと ミラーリング という 2 つの機能を提供しています。ショートカットとは ファイルシステム の シンボリックリンク のようなイメージで、データの実体は取り込み元にあるままで Microsoft Fabric で取り扱えるようにする仕組みです。データを移動させることなく分析ができるという非常に強力な機能となっています。一方の ミラーリング は取り込み元のデータをシームレスに OneLake にコピーする仕組みとなっており、データの取り込み作業の簡略化が期待できます。 現時点でショートカットは Azure Data Lake Storage Gen2 や Amazon S3 、Dataverse が、 ミラーリング は Azure SQL Database や Snowflake 、Azure CosmosDB などがそれぞれ対応しています。今後もショートカットにはオブジェクトストレージ系のサービスが、 ミラーリング にはデータベースや NoSQL 系のサービスが追加されていくのではと予想されます。 Data Factory Microsoft Fabric で ETL の役割を果たすのが Data Factory です。Azure Data Factory と同様に 100 を超えるコネクタを有し、オンプレミスや/ クラウド を問わず様々な場所のデータを Microsoft Fabric と連携させることが可能です。 GUI による処理の定義/パイプライン実行/ログの確認が可能となっており、Dataflow Gen2 という新しいエクス ペリエ ンスの提供に加え、Copilot for Data Factory もパブリックプレビューとなり AI アシスタントを活用したフロー開発が順次利用可能となる予定となっています。 また、GA のタイミングで Virtual Net Data Gateway がパブリックプレビューとなりました。これにより Azure 環境内にある分析データと Microsoft Fabric の通信をよりセキュアに実現できるようになるため、データ連携の選択肢の一つとしての活用が期待されます。 Synapse Data Engineering 大量のデータを変換しレイクハウス アーキテクチャ を構築するデータエンジニアを支援するための機能が Synapse Data Engineering です。Synapse Data Engineering によってデータエンジニアは Notebook を用いた Spark 実行環境を利用可能となります。 現時点で Synapse Data Engineering のランタイムには Spark 3.4、Delta 2.4、 Java 11、 Python 3.10 が含まれており、今後の最新バージョンへの追従は Microsoft Fabric で管理・対応されます。また、ノートブックとレイクハウスの Git 統合、Environment アーティファクト による構成管理、 VS Code 拡張機能 などがパブリックプレビューとなっており、データエンジニア向けの開発環境が順次拡充されていることが伺えます。 Synapse Data Engineering においても Copilot がパブリックプレビューとなっています。これにより Notebook 上で AI と対話しながら任意のコードを記述・実行していくようなことがまもなく実現可能となります。 Synapse Data Science ビジネスにおける洞察・予測のためのデータサイエンス実行管理機能が Synapse Data Science です。データの探索から始まり前処理、モデル作成とその管理までデータサイエンスに必要な機能が網羅的に提供されます。 今回の GA に合わせて Synapse ML 1.0 がリリースされています。これは大規模な 機械学習 のアプリケーションを簡素化する Spark 用の オープンソース ML ライブラリで、MLFlow に加え Azure AI Search でのベクトル検索や Azure Open AI Service 統合のための API などが含まれます。 Synapse Data Engineering の項で述べた Notebook の Copilot は Synapse Data Science でも同様に提供予定となっており、データサイエンス領域における AI 活用を促進する機能がそろった環境といえるかと思います。 Synapse Data Warehouse Microsoft Fabric ではオープン データ形式 をネイティブにサポートする次世代のデータウェアハウスとして Synapse Data Warehouse が提供されます。オープン データ形式 とは OneLake の項で述べた Delta-Parquet 形式のことであり、OneLake 上で管理される Parquet ファイルに対して SQL の API を発行し分析を行うというのが大まかな処理のイメージとなります。 Synapse Data Warehouse についてはパブリックプレビュー後も継続的に機能強化が行われていましたが、今回の GA のタイミングでもいくつか新しい発表がありました。一例をあげると SQLPackage や REST API による プログラマブル な開発のサポート、Query Insights によるソリューション監視、 SQL 動的データ マスキング ( DDM ) を使用したアプリケーションの保護などです。前述の ミラーリング の機能についても、データベースが主対象になりそうなことを踏まえると Synapse Data Warehouse との親和性が高い機能に見えています。 Synapse Real-Time Analytics 昨今の分析に必要なデータは多種多様となっており、IoT デ バイス や API からのリアルタイムデータも例外ではありません。Synapse Real-Time Analytics はログ、イベント、テレメトリといったリアルタイムデータを分析するためのサービスです。 Synapse Real-Time Analytics においてもレイクセントリックな思想は受け継がれており、データが OneLake 上で管理されることに変わりはありません。また、OneLake ショートカットとして Azure Data Explorer のソースデータベースを設定できるため、既存の Azure Data Explorer 環境に対しての KQL 発行といったこれまで Azure 上で実施していた分析エクス ペリエ ンスが Microsoft Fabric 上でも実現可能となっています。 Synapse Real-Time Analytics を理解するうえで重要な要素がイベントストリームです。これは受信したリアルタイムイベントをシームレスに取り込みキャプチャ・変換した後に Microsoft Fabric のさまざまな宛先にルーティングするという、データの中継役を果たします。ソース・宛先ともに複数の形式をサポートしており、リアルタイムデータの分析をする上では欠かせない仕組みといえます。 Power BI Microsoft が長年にわたり提供してきた Power BI が、今回 Microsoft Fabric に統合されました。現在 Power BI をお使いのユーザーは適切なライセンスを割り当てることで自身の環境で Microsoft Fabric の機能を使っていくことが可能になります。 Power BI に関してはパブリックプレビュー公開当初から魅力的な機能が追加されていきました。その一つが Direct Lake モードです。従来の Direct Query モードとインポートモードの長所を掛け合わせた、リアルタイムかつ高速なレポート表示を実現した機能で、今後のレポート開発で標準となっていくことが期待されます。 Power BI Desktop の開発モードで Git 統合がサポートされレポートおよびセマンティックモデル(従来のデー タセット )のバージョン管理が可能となったのも嬉しいアップデートです。現在対応する Git リポジトリ は Azure DevOps のみですが、今後 GitHub への対応がなされていくとより利用の幅が広がってくると思われます。 Data Activator これまで紹介してきた機能は Azure や M365 で類似のサービスが存在していましたが、この項で紹介する Data Activator は Microsoft Fabric で新しく登場した機能です。データ分析においては得られた洞察から何かしらのアクションを起こしていくわけですが、それを人手で実施するのは限界があるため自動化の仕組みが必要となります。 Data Activator はそのようなニーズに応える機能となっており、特定のルールに基づく分析結果をトリガーとしてその後のアクションを実行するまでをノーコードで実装できます。使用例としては、来月の在庫予測が しきい値 を下回りそうな分析結果が出たため Teams で関係者に通知するとともに後続のアクション実行のための API を呼びだすといった処理などが考えられます。 イベントの検知箇所として現在対応しているのは Power BI のセマンティックモデルと Synapse Real-Time Analytics のイベントストリームの 2 か所となっており活用の場面が限られますが、今後拡充されて利用シナリオが広がっていくことを期待したいです。 Purview Power BI と同様に Microsoft Purview も Microsoft Fabric に統合されました。これによって提供されるようになるのが Purview ハブで、これまでデータカタログと監査で分かれていた UI の入り口が一つに統一されます。 Microsoft Fabric 上のアイテムに対してデータカタログおよび監査機能が適用されることとなり、 Microsoft Fabric にデータを集めることで自然にデータガバナンスが向上する仕組みとしていくことも可能といえます。 まとめ 各機能の紹介としては以上となります。ここまで読んでいただくだけでも非常に多くの機能の集合体であることがお分かりいただけたかと思います。個々の機能において紹介しきれていない発表などもたくさんありますので、気になる方は Microsoft の公式ドキュメントやブログもぜひチェックしてみてください。以下にリンクをまとめておきます。 Microsoft Fabric のドキュメント Prepare your data for AI innovation with Microsoft Fabric—now generally available(MSの公式ブログ) Fabric workloads are now generally available!(MSの公式ブログ) 最後までお読みいただきありがとうございました。 アドベントカレンダー は本日から始まり今月いっぱい続いていきます。明日以降も面白い記事が目白押しですので、ぜひご覧ください。 私たちは一緒に働いてくれる仲間を募集しています! クラウドアーキテクト 執筆: @yoneya.fumihiko 、レビュー: @yamashita.tsuyoshi ( Shodo で執筆されました )
X イノベーション 本部デジタルエンゲージメントセンターの橋詰です。普段は金融機関向けに Salesforce (Financial Services Cloud)を導入するプロジェクトのPMや、MuleSoft Anypoint Platformを用いたソリューションのビジネス開発などを担当しています。あしかけ2年程かかりましたが、今年、 技術士 ( 情報工学 部門)に合格・登録をすることができました。 技術士 の試験は複数の段階がありまして、2年かかったと言っても実は、一次試験・二次試験(筆記)・二次試験(面接)とそれぞれ一発で合格することができました。 技術士 とはどういった資格なのかと、合格にいたるまでにどんな勉強をしたのかをまとめます。 技術士って何? なぜ受験したの? SIerのエンジニアはどの部門を受けるの? 技術士にはどんな試験があるの? 私がおこなった第一次試験の対策をご紹介 第一次試験の内容 試験の準備 専門科目の対策→普段勉強していれば大丈夫 適性科目の対策→せっかくなので技術者倫理を学ぶ 基礎科目の対策→30代後半はつらい 試験会場の様子 おわりに 技術士 って何? 日本 技術士 会の説明を引用すると、 技術士 とは、 「科学技術に関する技術的専門知識と高等の応用能力及び豊富な実務経験を有し、公益を確保するため、高い技術者倫理を備えた優れた技術者」の育成を図るための、国による資格認定制度( 文部科学省 所管)です。 https://www.engineer.or.jp/contents/about_engineers.html とのことです。知識や実務経験に加えて、技術者としての倫理観を持つことを期待されています。 なぜ受験したの? 受験を考え始めたのは30代中盤でした。当時は「 技術士 」という資格の存在をぼんやりと知っているだけでした。そのころITコンサルの案件でご一緒したエンジニアの先輩方が 技術士 の資格を 保有 していたことや、会社の先輩でもお持ちの方に出会い、触発されたことがきっかけです。中堅エンジニアとして次のステップに進むために挑戦しようと考えました。さらに、技術者倫理について再学習できることと、これまでのエンジニア経験の振り返りに良いと思ったことも動機です。 SIer のエンジニアはどの部門を受けるの? 私は 技術士 の 情報工学 部門: ソフトウェア工学 をターゲットに勉強をしました。IT関連の仕事についている人は技術部門の中の「 情報工学 部門」を目指すことになると思います。さらに技術部門は選択科目に分かれており、コンピュータ科学・ ソフトウェア工学 ・情報システム・情報基盤のいずれかを選ぶことになります。 技術士 にはどんな試験があるの? 簡単にご紹介すると、 第一次試験 基礎科目・適性科目・専門科目に関する択一式試験 第二次試験(筆記) 小論文の論述試験 第二次試験(面接) 面接による口頭試験 が行われます。テストのガイドについては改訂もありますので、日本 技術士 会のホームページをチェックしてください。 https://www.engineer.or.jp/contents/become_engineer.html 私がおこなった第一次試験の対策をご紹介 3つの試験を一回の投稿で書くと長くなりますので、今回は第一次試験の受験対策を紹介します。 第一次試験の内容 第一次試験は択一式試験(つまり、 マークシート 方式)です。基礎科目・適性科目・専門科目の3科目の出題となります。 試験の準備 IT業界では「 技術士 」は比較的マイナーな資格です(一方で「建設」ではかなりメジャー)。そのため、 技術士 情報工学 部門むけの試験勉強に関する情報が少ない状況です。そこで試験対策勉強に必要な情報や傾向を把握するために、網羅的な情報をどうにか収集する必要があります。界隈では有名な「 sukiyaki塾 」というコミュニティサイトでは盛んな情報発信が行われていますのでここは要チェックです。また sukiyaki 塾が出版している試験ガイド本( 独学・過去問で効率的に突破する! 最新版「技術士試験」勉強法 (DOBOOKS) など)もまず通読することがおすすめです。 専門科目の対策→普段勉強していれば大丈夫 さて、個別の対策です。まずは専門科目の対策です。技術部門として自身の専門科目を選択します。私が選択した 情報工学 部門の場合、試験の難易度は「応用 情報処理技術者試験 」の午前試験レベルと認識しておくことが妥当です。普段ITに関する情報のキャッチアップを行い、専門書・技術書を読み、春・秋の 情報処理技術者試験 を受けている人は問題なくクリアできる難易度でした。試験対策用の勉強をする場合は、応用 情報処理技術者試験 の対策本を利用することがおすすめで、そのため学習教材の選択肢も豊富でとっつきやすいです。私は 情報処理技術者試験 の勉強ではTACの教材を利用することが多いため、こちらの問題集( 情報処理技術者試験 ALL IN ONE オールインワン パーフェクトマスター 共通午前1 2024年度版 [出題実績リスト付き 出題可能性が高い問題がわかる!](TAC出版) )を利用しました。 適性科目の対策→せっかくなので技術者倫理を学ぶ 適性科目は、技術者倫理や 技術士 に関連する法律を問う科目です。試験対策は 技術士法 の把握などになります。まずは過去問を解いてみて苦手分野を把握し、知識を補充する対策になります。ぜひおすすめしたいのは、せっかくの機会を利用し「技術者倫理」について数冊本を読んでみることです。会社に勤めている日常で技術者倫理を積極的に学ぶ機会は少ないです。私も貴重な学習機会だと考え、以下のような書籍やサイトを使って学びを深めました。 書籍  技術者倫理の世界 第2版 書籍  失敗学のすすめ (講談社文庫) 最近であれば失敗学に関する新しい書籍が出ています: 新 失敗学 正解をつくる技術 サイト  日本技術士会HP 技術士倫理要領 基礎科目の対策→30代後半はつらい 基礎科目は、科学技術全般に関する基礎知識を問う試験です。実はこの試験が30代後半には一番辛いです。出題範囲は「科学技術全般」(お題目・カテゴリは決まっている)で、難易度は大学学部にて学習する授業のレベル。自分が専門とする分野ならまだしも、物理や化学、電気・電子、環境などの専門外の分野を、30代後半のいま思い出すのはかなり大変でした。学びなおしとなると、範囲も広く、ちょっと途方にくれます・・・。今回はどうにか合格点を取れたので良かったわけですが、学習の過程で下記を感じました。 (そもそも)第一次試験は20代のうちに受験することがおすすめ 大学で学んだ記憶が新しいうちにチャレンジするのが良いですね。 とにかく過去問題をたくさんこなして積み上げる 問題慣れすること、重要テーマを頑張って学びなおし・暗記すること 過去問題については日本 技術士 会のホームページで公開されていますのでこれを利用しましょう。 日本技術士会HP 過去問題(第一次試験) 日本技術士会HP 技術士第一次試験 試験問題の正答 試験会場の様子 先ほども書いた通りIT分野ではマイナーな資格ということもあり、受験者の年齢層は比較的高い印象です。一次試験の会場で見かける他の分野(メジャーな建設や土木など)の受験者には大学生かなという年齢層の人がとても多いです。察するに、一次試験の受験タイミングの理想形は、大学院の入試勉強が終わったあとについでに 技術士 一次試験もチャレンジすることなのかもしれません。その年齢だと専門科目がやや難しく感じるかもしれませんが、年齢が上がった後にぶつかる難関の基礎科目を効率的に勉強・合格できそうです。といっても、私の場合、この資格の存在を知ったのが30代中盤だったわけで…布教活動を頑張ろうと思います。 おわりに 30代後半で受験した 技術士 一次試験の対策方法をまとめました。 普段からITの基礎学習は頑張っておく 適性科目はついでに技術者倫理の勉強をするのがお得 基礎科目は難しいので過去問を頑張ってたくさん解く これで一次試験は独学でもクリアできると思います。なお、当社ではこのような資格取得のための教材費や受験手数料をサポートする制度もあります。今回は下記の支援を受けて受験しました。 資格試験の勉強に利用する書籍の購入費用 試験の受験手数料 加えて、 技術士 合格後の免許登録税なども会社から全額サポートしてもらえました。(合格後の細かいお話は後日書きます) さて次の壁は二次試験(筆記)です。本当の壁はこの筆記です。続きはまた書きたいと思います。 私たちは一緒に働いてくれる仲間を募集しています! Mulesoftコンサルタント(顧客接点DX・CRM領域) CRMソリューションコンサルタント 執筆: @hashizume.hideki 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )
X イノベーション 本部デジタルエンゲージメントセンターの橋詰です。普段は金融機関向けに Salesforce (Financial Services Cloud)を導入するプロジェクトのPMや、MuleSoft Anypoint Platformを用いたソリューションのビジネス開発などを担当しています。あしかけ2年程かかりましたが、今年、 技術士 ( 情報工学 部門)に合格・登録をすることができました。 技術士 の試験は複数の段階がありまして、2年かかったと言っても実は、一次試験・二次試験(筆記)・二次試験(面接)とそれぞれ一発で合格することができました。 技術士 とはどういった資格なのかと、合格にいたるまでにどんな勉強をしたのかをまとめます。 技術士って何? なぜ受験したの? SIerのエンジニアはどの部門を受けるの? 技術士にはどんな試験があるの? 私がおこなった第一次試験の対策をご紹介 第一次試験の内容 試験の準備 専門科目の対策→普段勉強していれば大丈夫 適性科目の対策→せっかくなので技術者倫理を学ぶ 基礎科目の対策→30代後半はつらい 試験会場の様子 おわりに 技術士 って何? 日本 技術士 会の説明を引用すると、 技術士 とは、 「科学技術に関する技術的専門知識と高等の応用能力及び豊富な実務経験を有し、公益を確保するため、高い技術者倫理を備えた優れた技術者」の育成を図るための、国による資格認定制度( 文部科学省 所管)です。 https://www.engineer.or.jp/contents/about_engineers.html とのことです。知識や実務経験に加えて、技術者としての倫理観を持つことを期待されています。 なぜ受験したの? 受験を考え始めたのは30代中盤でした。当時は「 技術士 」という資格の存在をぼんやりと知っているだけでした。そのころITコンサルの案件でご一緒したエンジニアの先輩方が 技術士 の資格を 保有 していたことや、会社の先輩でもお持ちの方に出会い、触発されたことがきっかけです。中堅エンジニアとして次のステップに進むために挑戦しようと考えました。さらに、技術者倫理について再学習できることと、これまでのエンジニア経験の振り返りに良いと思ったことも動機です。 SIer のエンジニアはどの部門を受けるの? 私は 技術士 の 情報工学 部門: ソフトウェア工学 をターゲットに勉強をしました。IT関連の仕事についている人は技術部門の中の「 情報工学 部門」を目指すことになると思います。さらに技術部門は選択科目に分かれており、コンピュータ科学・ ソフトウェア工学 ・情報システム・情報基盤のいずれかを選ぶことになります。 技術士 にはどんな試験があるの? 簡単にご紹介すると、 第一次試験 基礎科目・適性科目・専門科目に関する択一式試験 第二次試験(筆記) 小論文の論述試験 第二次試験(面接) 面接による口頭試験 が行われます。テストのガイドについては改訂もありますので、日本 技術士 会のホームページをチェックしてください。 https://www.engineer.or.jp/contents/become_engineer.html 私がおこなった第一次試験の対策をご紹介 3つの試験を一回の投稿で書くと長くなりますので、今回は第一次試験の受験対策を紹介します。 第一次試験の内容 第一次試験は択一式試験(つまり、 マークシート 方式)です。基礎科目・適性科目・専門科目の3科目の出題となります。 試験の準備 IT業界では「 技術士 」は比較的マイナーな資格です(一方で「建設」ではかなりメジャー)。そのため、 技術士 情報工学 部門むけの試験勉強に関する情報が少ない状況です。そこで試験対策勉強に必要な情報や傾向を把握するために、網羅的な情報をどうにか収集する必要があります。界隈では有名な「 sukiyaki塾 」というコミュニティサイトでは盛んな情報発信が行われていますのでここは要チェックです。また sukiyaki 塾が出版している試験ガイド本( 独学・過去問で効率的に突破する! 最新版「技術士試験」勉強法 (DOBOOKS) など)もまず通読することがおすすめです。 専門科目の対策→普段勉強していれば大丈夫 さて、個別の対策です。まずは専門科目の対策です。技術部門として自身の専門科目を選択します。私が選択した 情報工学 部門の場合、試験の難易度は「応用 情報処理技術者試験 」の午前試験レベルと認識しておくことが妥当です。普段ITに関する情報のキャッチアップを行い、専門書・技術書を読み、春・秋の 情報処理技術者試験 を受けている人は問題なくクリアできる難易度でした。試験対策用の勉強をする場合は、応用 情報処理技術者試験 の対策本を利用することがおすすめで、そのため学習教材の選択肢も豊富でとっつきやすいです。私は 情報処理技術者試験 の勉強ではTACの教材を利用することが多いため、こちらの問題集( 情報処理技術者試験 ALL IN ONE オールインワン パーフェクトマスター 共通午前1 2024年度版 [出題実績リスト付き 出題可能性が高い問題がわかる!](TAC出版) )を利用しました。 適性科目の対策→せっかくなので技術者倫理を学ぶ 適性科目は、技術者倫理や 技術士 に関連する法律を問う科目です。試験対策は 技術士法 の把握などになります。まずは過去問を解いてみて苦手分野を把握し、知識を補充する対策になります。ぜひおすすめしたいのは、せっかくの機会を利用し「技術者倫理」について数冊本を読んでみることです。会社に勤めている日常で技術者倫理を積極的に学ぶ機会は少ないです。私も貴重な学習機会だと考え、以下のような書籍やサイトを使って学びを深めました。 書籍  技術者倫理の世界 第2版 書籍  失敗学のすすめ (講談社文庫) 最近であれば失敗学に関する新しい書籍が出ています: 新 失敗学 正解をつくる技術 サイト  日本技術士会HP 技術士倫理要領 基礎科目の対策→30代後半はつらい 基礎科目は、科学技術全般に関する基礎知識を問う試験です。実はこの試験が30代後半には一番辛いです。出題範囲は「科学技術全般」(お題目・カテゴリは決まっている)で、難易度は大学学部にて学習する授業のレベル。自分が専門とする分野ならまだしも、物理や化学、電気・電子、環境などの専門外の分野を、30代後半のいま思い出すのはかなり大変でした。学びなおしとなると、範囲も広く、ちょっと途方にくれます・・・。今回はどうにか合格点を取れたので良かったわけですが、学習の過程で下記を感じました。 (そもそも)第一次試験は20代のうちに受験することがおすすめ 大学で学んだ記憶が新しいうちにチャレンジするのが良いですね。 とにかく過去問題をたくさんこなして積み上げる 問題慣れすること、重要テーマを頑張って学びなおし・暗記すること 過去問題については日本 技術士 会のホームページで公開されていますのでこれを利用しましょう。 日本技術士会HP 過去問題(第一次試験) 日本技術士会HP 技術士第一次試験 試験問題の正答 試験会場の様子 先ほども書いた通りIT分野ではマイナーな資格ということもあり、受験者の年齢層は比較的高い印象です。一次試験の会場で見かける他の分野(メジャーな建設や土木など)の受験者には大学生かなという年齢層の人がとても多いです。察するに、一次試験の受験タイミングの理想形は、大学院の入試勉強が終わったあとについでに 技術士 一次試験もチャレンジすることなのかもしれません。その年齢だと専門科目がやや難しく感じるかもしれませんが、年齢が上がった後にぶつかる難関の基礎科目を効率的に勉強・合格できそうです。といっても、私の場合、この資格の存在を知ったのが30代中盤だったわけで…布教活動を頑張ろうと思います。 おわりに 30代後半で受験した 技術士 一次試験の対策方法をまとめました。 普段からITの基礎学習は頑張っておく 適性科目はついでに技術者倫理の勉強をするのがお得 基礎科目は難しいので過去問を頑張ってたくさん解く これで一次試験は独学でもクリアできると思います。なお、当社ではこのような資格取得のための教材費や受験手数料をサポートする制度もあります。今回は下記の支援を受けて受験しました。 資格試験の勉強に利用する書籍の購入費用 試験の受験手数料 加えて、 技術士 合格後の免許登録税なども会社から全額サポートしてもらえました。(合格後の細かいお話は後日書きます) さて次の壁は二次試験(筆記)です。本当の壁はこの筆記です。続きはまた書きたいと思います。 私たちは一緒に働いてくれる仲間を募集しています! Mulesoftコンサルタント(顧客接点DX・CRM領域) CRMソリューションコンサルタント 執筆: @hashizume.hideki 、レビュー: Ishizawa Kento (@kent) ( Shodo で執筆されました )