TECH PLAY

エス・エム・エス

エス・エム・エス の技術ブログ

271

こんにちは、カイポケの開発組織責任者をしている酒井です。 今日は私の大切な仕事の1つである「エンジニア採用」について書きます。この記事は 株式会社エス・エム・エス Advent Calendar 2025 の23日目の記事です。 「意思決定をスケールするエンジニア」がなぜ重要なのか エス・エム・エスの事業領域は、制度・業務・環境が複雑に絡み合う変化の大きい「社会課題」という不確実性の高い領域です。プロダクト開発において重要なのは、こうした不確実性と向き合いながら、試行錯誤を通じてソフトウェア設計へと落とし込み続けられるかどうかだと考えています。 事前に立てた計画どおりに進めれば問題が解決するわけではなく、絶対的な正解が存在しない中で、状況に応じた判断を積み重ねながら物事を前に進めていく力が求められます。そのためには、特定の個人の力量に依存するのではなく、組織としてスキルやマインドセットをバランスよく身につけていく必要があります。 私たちが採用したいエンジニアは、単に経験が豊富な人という意味での「強い個人」ではありません。実装が速いことや難しい技術に詳しいことは前提条件の一部にすぎず、本当に重視しているのは、判断を引き受け、学習をチームに広げ、不確実性の中でも組織として前に進められる状態をつくれるかどうかです。 プロダクトや組織が成長するにつれ、意思決定は一部の人に集中しやすくなり、結果としてスピードを失ってしまうことがあります。そのボトルネックを解消するためには、強い個人を増やすこと以上に、判断と学習が分散する構造をつくることが重要だと考えています。 このような「意思決定をスケールするエンジニア」に対して、私たちは何を大切にし、採用の現場ではどのような点を見ているのかについて以降で整理していきます。 何のための「技術力」か 私たちの採用プロセスでも、他の多くの企業と同様に、ソフトウェアエンジニアの選考において「技術面接」を行っています。ここでは、過去のご経験を伺いながら現実の問題やビジネス上の課題をどのように捉え、ソフトウェアとしてどのように設計してきたのか、その難易度やスケール感などを理解させていただいています。 技術面接の結果は、能力を把握するうえで非常に重要な情報ではありますが、それだけで採用を決める十分条件とはしていません。特により高い期待役割を担っていただくポジションになるほど、技術的な正しさだけで問題を閉じてしまわず、周囲の思考を広げ、チーム全体の学習速度を高める関わり方ができるかどうかも含めて見ていきたいと考えています。 問題解決の能力 前述のとおり、私たちが向き合っている事業領域には常に高い不確実性が存在します。ときには、機能を開発する意味(WHY)そのものが明確に定義されていない状態で向き合うこともあります。 そのような状況において私たちが期待しているのは、「これはプロダクトオーナーが決めること」と線を引くことではなく、必要なコンテキストを集め、自分ごととして課題設定に関わりながら少しずつソフトウェア設計の材料をつくっていく姿勢です。 表層的に現れている問題だけを塞ぐのではなく、なぜその問題が起きているのかを考え、アーキテクチャや組織、プロセスといった複数の観点を行き来しながら構造的に課題を捉え直していくことが重要であり、そのための手段として「技術」を使っているエンジニアと一緒に仕事をしたいと私たちは考えています。 面接では「設計」の経験について多く伺いますが、一般論としての設計ではなく、向き合ったドメイン固有の不確実性に対してどのような設計判断を行ったのか、その設計が時間の経過とともにどのように変化していったのか、複数の選択肢の中からなぜその判断を選んだのか、何を守り、何を捨てたのかといった「判断の背景」を重視しています。 リーダーシップのあり方 技術力と同様に、採用においてはエンジニアとしての「リーダーシップのあり方」も大切にしています。 私自身は、強いリーダーシップに必ずしも肩書きは必要ないと考えています。権限の有無に関わらず、状況を理解し根本的な課題を設定しながら物事を前に進めていく力や、意見の対立を恐れずに状況を整理し、挑戦の道筋を描いていく力こそが重要だと考えています。 これまで多くの面接を担当してきた中で、複雑な問題解決を経験してきたエンジニアの多くは、再現性のある「技術以外の能力」を併せ持っていると感じることが多くありました。特に、社会的背景や業界特性、ビジネス上の文脈といったコンテキストを理解しようとする姿勢が強く、「なぜ(WHY)、このタイミングで(WHEN)、誰のために(WHO)、この問題を(WHAT)、解く必要があるのか」といった点について、解像度の高い説明をしていただけることが多い印象です。 また、そのようなリーダーシップを発揮する方ほど、他者や状況からのフィードバックに対しても柔軟であるように感じます。他者からの指摘や、判断の結果としてユーザーから寄せられた意見に対して、防御的になるのではなく自分の前提を疑い問題を捉え直そうとする姿勢を持っているかどうかを大切に見ています。 面接の場では、私自身が理解しきれなかった点や違和感を覚えた点については率直に質問するようにしています。もちろん、意図的に揚げ足を取るような聞き方をすることはありませんが、お互いの考えをすり合わせるための対話として、その背景や判断理由を丁寧に伺うようにしています。 制約が強い環境であること 問題解決力やリーダーシップに加えて、外部環境による制約と向き合いながらエンジニアリングを行ってきた経験があるかどうかも、大切な観点の1つです。 法制度や業界特有の商習慣、リソースや時間の制約、大規模で複雑なソフトウェアといった前提条件の中で、理想を理解しつつも現実的な着地点を見出してきた経験やその中で「将来変えられるもの」と「変えられないもの」をどのように切り分けて考えてきたのかは、必ず伺うようにしています。 介護業界においては、複雑な法制度が顧客業務にとって大きな制約となり、同時にソフトウェア設計にも強く影響します。これらを無視することはできない中で、何を選び、何を捨てるのかという判断を積み重ねてきた経験は、私たちが特に大切にしたいポイントです。 頭数で解決しない採用 私たちは、複雑で不確実性の高い社会課題に向き合いながらソフトウェア開発を行っています。もちろん、ここまでに書いたすべての能力や経験を一人のエンジニアに求めているわけではありません。 採用において私が大切にしているのは、人数を目標にして「強い個人」を集めることではなく、未来の「強いチーム」をつくるために必要な視点や役割を持った方と出会うことです。 選考の場で多くのエンジニアの方と対話する中で、私自身も日々多くの学びを得ています。これまでエス・エム・エスの採用に関わってくださったすべての方に感謝しつつ、これからも、組織の未来を一緒につくっていける方との出会いを大切にしていきたいと考えています。 引き続き、カジュアル面談や選考へのご応募をお待ちしています。
この記事は 株式会社エス・エム・エス Advent Calendar 2025 の22日目の記事です。 はじめに こんにちは! ウェルミージョブ 、 シカトル 、 カイゴジョブアカデミー でエンジニアリングマネージャーとプロダクトマネージャーを担当している 豊濱 です。 自己紹介は先日の記事をご覧ください。 tech.bm-sms.co.jp 今回は「作らない技術」についてお話します。 ものづくりに関わるコストや時間が大きく減らせる時代になったからこそ、こういった視点を持って取り組むことで本質的な課題に取り組めるのでは、と考えています。 いつもやっていること プロダクト開発に関わっている方は、細かい違いはあれど概ね以下の流れで進めていることが多いのではと思います。 現状や市場、顧客の分析 達成したい目的はなにか 提供できる価値はなにか プロダクトとして提供すべきものはなにか 設計、開発、テスト、リリース 検証 1〜3番あたりに戻り、発展させる ものづくりをするために、感覚や定性ではなく、目的や価値を明確にして、チーム全体で同じ目線を持って取り組むのはとてもいいことです。 ただそれを検証するために「なにかものを作らないといけない」という流れが当然になっていないでしょうか。 なにかを作るには人件費やインフラ・アプリケーションの構築、リリースをするのであれば運用やメンテナンス・顧客対応、そしてそれらをこなすための「時間」など、投資が必ず必要になってきます。そこへ至る前にまだやれることがたくさんあるのでは、と考えています。 作らないための工夫 いまあるものの組み合わせや見直しでどうにかする 社内ツールの使いづらさを解消したい リードタイムを短くしたい 人的リソースを最適化したい 複雑なフローをなくしたい こういった目的や成果をもって進めることはよくあります。 新しいプロダクトで価値提供するのが適切な場合もありますが、いまあるフローをガラッと変えるのも大きなコストと時間がかかってしまいます。 いまの複雑なフローを全く新しいシンプルなものにする →いまのフローのなかで、待ちが発生している部分を並列化する 複数ある管理画面を1つに集約する →複数の管理画面は変えず、まずはデータの連携を人手(コピペ)でやっている部分を自動化する といったところから入るのも次に進める大きな一歩だと考えています。 現状の理解や可視化に時間がかかってしまうのでは、という見方もありますが、なぜそれが存在しているのか?を確認することは新しくプロダクトを作るにしても必要なプロセスなので、全く無駄になるとはあまり考えていません。 そのプロダクト・業務をなくしたらどうなるのか もはや、作らないどころか作ってあるものをなくす話になっていますが、いまあるものが本当に必要なのか、という検証もやっていくべきです。 なくすことで失われる価値はなんなのか 維持していくための投資を鑑みるとどうなるのか 新しくプロダクトを作って移行させるコストとのトレードオフはどうなのか 実はなくすだけで、目的が達成できるのではないか もちろん、単なる投資対効果やトレードオフだけで判断できるわけではありませんが、発想として「なくしてみる」も考えていくのが大事だなと思います。 まとめ さまざまな技術ソリューション・近年の生成AI・IDEに代表されるツールによって、10年前に比べて作るハードルは圧倒的に下がり、作りながら試行していいものに発展させていく、というのがスタンダードな時代になってきました。 そんな時代だからこそ、「いかに作らずに成果を出せるか」みたいな視点を持っておくのも1つの「技術」なんじゃないかなと考えて、こんなタイトルをつけてみました。
この記事は 株式会社エス・エム・エス Advent Calendar 2025 の19日目の記事です。 こんにちは。エス・エム・エスの人材紹介開発グループでマネージャーをしている @kenjiszk です。今回はカジュアルな私の悩みについて書いてみたいと思います。 コードを書かないマネージャー 業務でコードを書くかどうかはマネジメントしている領域や組織規模に寄ると思いますが、私は現在、業務において「コードを書かないマネージャー」というスタイルをとっています。コードを書くことが嫌いではないですし、実際にコードを書くことで手触り感を持ってプロダクトを扱うことは非常に好きです。ただし、マネジメントという観点において以下の理由でコードを書くことをしていません。 マネジメント業務に関わらず、仕事はレバレッジが効くポイントに力を割くことが良いと考えている 残念ながらスーパーエンジニアではない私は自分がコードを書くことで効かせられるレバレッジよりも、マネジメント業務によって事業に与えられるレバレッジの方が大きいと感じている むしろ、今の状態で中途半端にコードを書き始めると2種類のボトルネックを発生させる 1つ目は、兼務としてコードを書くので、おそらく実装速度やクオリティは高くない、大きなissueは扱えない 2つ目は、コードを書くことに時間を使うことで、本来するべき意思決定や戦略づくりなどに時間が割けなくなる ということで、意図的にコードを書いていないし、それが良いと思っています。 生成AIの登場 ただ、この状況は自分が過去にコードを書いたことがあるから成立しているとも言えます。また、SREやらマイクロサービスの運用やらもやっていた経験があるのでシステム全体を通してある程度理解できるという前提があり成立していそうです。 そんなこんなでまあなんとかやっているわけですが、最近はこんな事をよく口にしているなあと思いました。 「その辺はAIに書かせちゃっても大丈夫そうですね」 「この処理はAIが得意そうなんで書かせちゃいましょうか」 「AIでコード書くの当たり前になってきてますねー」 そして気づきました、はて、私はAIを活用してコードを書いたことあったっけ?、と。 コードを書かないマネージャーはどこでAIを使ってコードを書く? やったことがないならやってみればいいのですが、私はコードを書く業務をしていないのでAIを活用したコーディングを試す場所がありません、どうしよう。 無理やり業務の中にコーディングのタスクをねじ込んでも、前述のように自分がボトルネックになることは目に見えています。じっくり腰を据えて取り組めば良いのでしょうが、色々な仕込みをしている最中でもあって、そっちはそっちで時間を割かないといけない状況でした。 であればもう個人開発しかなさそうです。 以前は個人開発をしていたこともあったのですが、なかなか継続的にコードを書く時間が確保できるわけでもないのでここ数年は断念していました。AIがコードを書いてくれるなら時間をそこまで使わなくても何か作れそうなので個人開発を再開してみることにしました。 このブログで伝えたいことの主題ではないのでアプリの機能や中身については触れませんが、Flutter + Firebaseという構成でシンプルなiOSアプリを作ってみました。デザインも含めて実装していて、なんとなくの雰囲気は以下のようなものになります。 やって良かったvibe coding AIによるコーディングについてはあらゆるところでその効果が語られていますので改めてここでまとめるつもりはないですが、実際に手を動かしてやってみたことは価値があったなと思います。 まず当たり前の話ですが、圧倒的に便利でした(笑)。 first commitが2025/11/6ですが、そこから週に数時間空いた時間を使う程度で約1か月で概ねの機能を作り終えることができました。シンプルな構成とはいえ、Firebaseによる認証周り、Firestoreへのデータ保存、トップページから複数ページへの遷移など、一通りの機能を持つアプリです。これらが予想外に簡単に作れてしまいました。 個人的に特に便利だと感じたのは、実現したい機能の概要を伝えると、それに適したライブラリの選定から提案してくれる点です。最新の言語・フレームワーク事情をそこまでキャッチアップできていない身としては、この辺りの調査の時間を大幅にショートカットできるのは非常に助かりました。 AI開発は領域によって、能力のスケールアウトをしてくれる場合とスケールアップをしてくれる場合があるということもわかりました(スケールアウト/スケールアップは本来インフラ用語で、それぞれ「台数を増やして処理能力を上げる」「単体の性能を上げる」という意味です。ここでは「自分と同じ能力を持つ分身を増やす」「自分にない専門能力を獲得する」という意味で使っています)。 自分が得意な領域や実現方法を詳しく知っている箇所では能力をスケールアウトしてくれる感覚になります。私の場合は、Flutter + Firebaseという構成でアプリを作ることは何度か経験があるので、この部分は自分が出来ることを代わり単に高速でコーディングをしてくれているという感覚でした。自分がもう一人いる感覚です。 一方で、デザインだったりアプリのアイコンの作成というところでは、私は専門家ではないのでなんとなくのイメージを伝えるだけで、それなりのクオリティのものを作り出してくれました。ここは確実に能力のスケールアップがされている実感があり、AIを使っていて一番テンションが上がるポイントでした。これは自分がもう一人いるというよりは、専門家が自分のために働いてくれているという感覚でした。 別の観点として、自分で手を動かすにはちょっとテンションが上がらないけどやらないといけないタスクは全部AIがやってくれるのはとても良く、私の場合は、ストアにアプリを出すための設定やストアに表示する魅力的な文言作成は全然やる気が出ないのでこの辺りを全部任せられるのはとてもありがたいなと思いました。これは文句を言わない秘書的な感覚です。 ちなみに全く新規の言語やフレームワークだときつそうだなというのも同時に感じました。少なくとも私が扱うと、言語やフレームワークの特徴や設計方針などを理解していない状態でAIに任せると結構酷いものが出来上がってきそうです。 また、実装についてはマルっと任せると冗長で適当なただ動くだけの巨大なコードを出してくるので、必然的に意味のある最小単位の指示をAIに出すことになり、細かい修正を少しずつ積んでいくというスタイルに自然となりました。 最後に AIによるコーディングでアプリ開発をするという実績を解除しましたので、今後は自信を持って「これ系の処理はAIが得意そうだからAIに書かせましょう」とか「AIで開発するとレビュー大変ですよね」と声高に言っていこうと思います! 冒頭で触れた、「コードを書かないマネージャー」という選択も今後変わってくるかもしれません。今回はAIをコーディングに活用する部分だけに触れていますが、あらゆる業務でAIの活用は積極的にしていきたいと考えています。 AIの登場によりどんなことでも色々と触って試してみるコストが大幅に下がったと思うので、積極的に新しいことを取り入れチャレンジする組織を目指していきます。
はじめに この記事は 株式会社エス・エム・エス Advent Calendar 2025 の18日目の記事です。 はじめまして。エス・エム・エス プロダクト推進本部 採用・組織開発支援グループの韓です。 今年の8月に入社したばかりですが、なぜ私がエス・エム・エスに入社したのか、今やっていること、そして今後やっていきたいことを紹介します。 今までの経歴 前職はデジタルマーケティングSaaSを提供する企業に所属していました。2018年にエンジニアとして入社し、約5年間開発に携わりました。開発業務だけでなく、チームリードとしてのマネジメントや外部登壇など、様々な経験をさせてもらいました。 チームで開発したプロダクトがスピーディーに形になり、ユーザーから嬉しいフィードバックが届く瞬間こそ開発の醍醐味だと感じ、エンジニアとして楽しく仕事に向き合っていました。 転機が訪れたのは、エンジニア採用が芳しくなく、誰かエンジニア採用を牽引する必要が出てきたときでした。エンジニアバックグラウンドがあり、コミュニケーションが比較的得意だった私に白羽の矢が立ち、2023年7月からエンジニア採用責任者としてのキャリアが始まりました。 面接官以外の採用業務は未経験でしたが、周囲の協力もあり、大変ながらも期待に応える成果を出すことができました。エンジニア時代に感じた、チームで開発したプロダクトがスピーディーに形になる体験において、優秀なチームメンバーが存在したことが1つの要因であると感じています。そのチームメンバーがいたのも当時の採用があったからこそであり、会社・組織・チームにとっては採用が重要であるのを身をもって感じました。また、組織やプロダクトの課題と候補者のキャリアに深く入り込むことで、なぜその候補者に入社してもらいたいのかのストーリーを作り、結果として候補者に熱量高く入社してもらえたときの嬉しさはかけがえのないものでした。そういった成功体験を通じて、採用をはじめとした「人・組織」に向き合う楽しさ、そして優秀なメンバーを採用することのインパクトの大きさを肌で感じました。 エス・エム・エスに入社した理由 前職での人事の仕事も楽しかったのですが、人事へのジョブチェンジから2年、在籍期間も6年半が経ち、「他にどのような環境があるのか」と外の世界にも興味を持ち始めました。 そんな中、現在のグループ長である @emfurupon777 とカジュアル面談をする機会があり、エス・エム・エスについて詳しく聞きました。特に刺さったのは、企業理念やミッション・バリューにあるように「続」を重視している点です。つまり、「長期を見据えて価値を出し続けること」を大事にしているという文化です。 エス・エム・エスが向き合う日本の高齢社会の課題は非常に壮大です。1年やそこらで解決できるものではなく、10年、20年というスパンで考えなければなりません。そのためには長期視点で思考し、継続的にアクションを取り続けることが重要になります。 私自身、そこまで長期で思考した経験はありませんでしたが、「将来組織を牽引する人材になるには、長期的な視座が必要だ」という課題感を持っていました。また、この壮大な課題に向き合う組織を作ることは非常にチャレンジングだと感じ、強く惹かれました。 選考過程で、技術責任者の @sunaot 、人材紹介開発部EMの @kenjiszk 、人事の @fkc_hr ともお話ししましたが、皆さんが優秀であることはもちろん、「エス・エム・エスを通じて社会を良くしたい」という熱い思いがひしひしと伝わってきました。そのパッションに感化され、次のチャレンジの場としてエス・エム・エスを選び、今年8月に入社しました。 今エス・エム・エスでやっていること 現在は、プロダクト推進本部のエンジニア採用をメインで進めています。 採用業務は多岐に渡りますが、時間的にも比重が大きいのは「カジュアル面談」と「候補者の選考フロー構築」の2つです。 カジュアル面談について 前職での経験から、「カジュアル面談でどれだけ自分たちに高い関心を持ってもらえるか」が候補者の意思決定における重要な要素だと考えています。また、入社時に期待されていたことの1つが、今までのエス・エム・エスにはない「私ならではの熱量・アプローチ」でした。そのため、自分の言葉でエス・エム・エスの魅力を語れるようになる必要がありました。 組織や事業のキャッチアップが落ち着いた入社1か月半頃から、まずは田辺さんやEM陣の面談に同席して見学。次に私が作成した資料を使ってメインで話し、 @sunaot や @emfurupon777 に同席してもらってフィードバックをもらう……というサイクルでブラッシュアップしていきました。皆さんとても協力的で、しっかりフィードバックをもらえる環境は本当にありがたいです! 採用チームでは今年9月以降、ダイレクトリクルーティングや紹介会社連携の強化により母集団形成がうまくいっており、私の9月から12月現在のカジュアル面談担当数も70件を超えました。 まだ精度を上げる余地はありますが、短期間で多くの機会をもらえたおかげで、候補者の方から「韓さんとの面談が有意義でした」といったポジティブな感想をいただけることも増えました。また、私が担当した候補者の方がオファーや内定承諾に至るケースも出てきています。 カジュアル面談で話すたびに、エス・エム・エスの向き合う課題の壮大さと、やるべきことの多さを再認識します。私が魅力を感じたときのように、候補者の方にも「今とこれからのエス・エム・エス」の魅力を感じてもらえるよう、今後も力を入れていきたいです。 選考フローの構築 入社して驚いたことの1つが、「候補者への向き合い」に相当な力を入れている点です。 現在は毎朝、採用チームでパイプラインを確認しています。各候補者の方にどのような選考フローを組むべきか、この場で決められない場合は誰に相談するかを話し合います。エス・エム・エスの選考は画一的なフローではなく、候補者ごとに柔軟にカスタマイズするため、しっかりとした議論が必要です。 当初は「ここまで時間をかけて決めるのか」と驚きましたが、エンジニア採用の難易度が年々高まる中、候補者一人ひとりに深く入り込む重要性を再認識しています。(もちろん、ただ時間をかければ良いわけではないので、効率化できる部分は工夫も必要ですが) 採用は人を巻き込む業務が多いですが、エス・エム・エスのメンバーはコミュニケーションが非常に円滑で、建設的な議論ができる方ばかりです。だからこそ、候補者に合わせた最適な選考フローが提供できているのだと思います。 これからやっていきたいこと 入社して5か月になりますが、今のところとても楽しく働いています。 私は、仕事を長く続けるには「その仕事が面白いか」が最も大事だと思っています。「面白い仕事」の条件は、「向き合っている課題が挑戦的であること」そして「一緒に働く仲間が優秀で良いメンバーであること」です。 重要なので繰り返しますが、エス・エム・エスの取り組んでいる課題は壮大で、一筋縄ではいきません。そのため、初めて会う候補者の方に一言で説明するのは難しいです。しかし、だからこそあらゆる切り口での魅力があり、候補者の入り口となる人事は、事業・プロダクト・組織・人に深く入り込み、広く知る必要があります。 まだ理解が浅い領域もありますが、その分、飽きずにやれることがたくさんあると感じています。そして、一緒に取り組む心強い仲間もいます。 つまり、腰を据えて長期であらゆることに取り組めそうだと思っています! まずは採用を軸にしつつ、人事として組織・人の観点で「今後どうあるべきか」を考え、日頃から問いを立ててアクションしていきたいです。 そして、エス・エム・エスではあらゆるポジションのエンジニア、デザイナー、PdMを募集しています。ぜひ私や現場のメンバーのカジュアル面談でお話しましょう。お待ちしています!
この記事は「株式会社エス・エム・エス Advent Calendar 2025」の12/17の記事です。 qiita.com はじめに 介護/障害福祉事業者向け経営支援サービス「カイポケ」でQAを担当している中村です。気づけば入社して4年が経ちました。現在は複数のQAチームに横断的に関わりつつ、チームのサポートや改善活動の推進、組織マネジメントなど幅広い業務を担当しています。 エス・エム・エスでは全社員が生成AIを業務に活用できる環境が整っており、私たちQAエンジニアもテスト活動や業務効率化に活用を進めています。しかし、現状は個人レベルでの活用がメインとなっており、組織的な仕組み化やナレッジの横展開という面では、まだまだ生成AIを活かしきれていないというのが実情です。 こうした課題に対し、今回の記事では生成AIを品質活動に取り入れようとしている具体的なチャレンジ事例について2つ紹介します。まだ充分な成果が出ているフェーズではなく、あくまで試行錯誤している内容として、率直に記載していますのでご了承ください。 事例1. 不具合分析を生成AIで効率化 導入の背景 カイポケでは、不具合データに複数の分類を持たせて、定量的に分析する仕組みを取り入れています。詳細は過去に私が執筆した記事をご参照ください。 tech.bm-sms.co.jp 不具合分析は主に以下のプロセスで進めていますが、生成AIを取り入れたのは「3.JIRAのデータを元に分析する」フェーズです。 不具合をJIRAチケットに起票 JIRAのデータをスプレッドシートで集計・可視化 JIRAのデータを元に分析する ※AI活用ポイント この「分析する」のフェーズは、分析経験・プロダクト理解・そして熟練者の勘所も必要であり、属人化しやすく時間が掛かってしまうという課題を抱えていました。そこで、構造化された不具合データを生成AIと連携させ、分析の作業効率化とプロセスの標準化を目指すことで、この課題を打破できると考えました。 どう実現しているか? 使用する生成AIはGeminiです。まず、JIRAに蓄積されている分析対象の「不具合データ」を用意し、インプットとしてAIに渡します。次に分析の目的や期待するアウトプットの形式といった具体的な分析指示をプロンプトで入力し、不具合分析を実施していきます。不具合データやプロンプトの詳細は後述します。 不具合データ 不具合データは、普段から集計・活用しているJIRAチケットの情報がベースです。このデータは、不具合の発生状況だけでなく、品質改善に向けた深掘り分析を可能にするため、複数の「分類軸」を持たせてています。 不具合データが持っている主要な情報は以下の通りです。 項目名 説明 基本情報 要約、再現手順、期待値など、不具合の概要情報 テストフェーズ 不具合を検出したテストフェーズ (例:DEVテスト、STGテスト など) 不具合種別 不具合の種別 (例:新規、既存 など) 検出種別 検出した不具合の内容 (例:機能不備、レイアウト不備 など) 検出分類 不具合を検出した経路 (例:QAテストケース、QAテストケース外など) 原因分類 不具合が混入した原因 (例:仕様理解不足、コード実装不備 など) プロンプト 分析の品質を均一化、誰でも悩まずに効率的にアウトプットが得られるよう、「標準プロンプト」を設計しました。この標準プロンプトは生成AIを特定の専門家として機能させるための要素を含んでいます。 標準プロンプトを構成する主な要素は以下の通りです。 構成要素 目的と具体的な指示 役割 ペルソナを設定し、出力のトーンと視点を設定する 背景 分析やテストの目的など、データでは分からない文脈を設定する ルール 具体的な分析作業を指示、分析軸の指定やアウトプットの構成要素を設定する ※プロンプト例 役割 ・経験豊富なQAチームリーダーの視点で分析してください 背景 ・分析目的:プロジェクトの品質傾向を把握したい ・プロジェクト名:XXX機能の追加 ・テスト目的:追加したXXX機能が正しく動作すること、関連する既存機能に影響がないことを確認する) ルール ・「検出種別 × 原因分類」の軸で分析をしてください ・不具合から品質傾向を客観的な視点でレポートしてください ・全体を通して「である調」で記述してください ・結論から先に述べる構成にしてください 今後に向けて 生成AIが最初に出してくるアウトプットはあくまで「下書きレベル」であるため、人間によるレビューやAIとの対話が多く必要になっています。今後は、チーム全体での積極的な活用とフィードバックを通じて分析精度の向上を図り、レビューのコストを削減できればと考えています。また、データ集計から言語化までのプロセスをより効率化するため、スプレッドシートのAI関数なども活用し、シームレスな連携を実現できるよう改善を進めていくことも検討していきます。 事例2. 不具合情報を持ったチャットボットの活用 導入の背景 テスト設計において、過去の不具合情報やドメイン知識は重要な参考情報ですが、情報が膨大ゆえに探索コストが高く情報が漏れてしまうというリスクがありました。生成AIはこれらの課題解決に加え、テスト観点の提案やレビュー効果も期待できるため、対話式のチャットボット作成を目指すことにしました。 どう実現しているか? GeminiのGem機能 を使い、「カスタム指示」と「知識」に必要な情報を設定することで専用のチャットボットを作成しました。プロンプトは入力に迷わないようにいくつかサンプルを作成して公開しています。運用イメージは下記図をご参照ください。 カスタム指示 ドメイン知識を持ったQA専門のアシスタントとして機能するように設定しています。カスタム指示には、AIが回答の際に参照すべき「役割」「ドメイン」「ルール」を詳細に定義しています。 カスタム指示に設定した内容は以下の通りです。 構成要素 目的と具体的な指示 役割 ペルソナを設定し、出力のトーンと視点を設定する (例:あなたは過去不具合とドメイン知識に精通したQAアシスタントです) ドメイン サービスの業界、業務領域、技術的・制度的な制約といった、背景知識を設定する ルール 行動指針(情報検索方法、事実に基づいた回答の徹底)と、アウトプットの構成要素を設定する 知識 知識には事例1で紹介した不具合データを設定します。 チャットボットとの対話例 実際にチャットボットとやりとしている内容の例を紹介します。最終的な判断は人が行う必要がありますが、叩きとしては充分な内容で高速で出力されることもあり非常に効率的です。 目的 プロンプト例 回答概要 1. リスク分析と観点抽出 ログイン機能に変更が入るので、過去の不具合から見て注意すべき観点を教えて 過去の不具合事例に基づき、 認証・セッション安定性 、 セキュリティ(権限昇格) 、 連携機能への影響 など、最もリスクの高い重点観点を提示 2. テストケースの提案 勤怠管理の改修が入るので、具体的なテストケースを提案して 過去事例を反映し、 境界値テスト や 機能連携テスト など、具体的な操作手順を含むテストケースの例を提案 3. 不具合発生時の対応支援 特定のデータで画面が真っ白になったけど、過去に似た事象はある? 類似する 過去の不具合事例 や 想定される原因 を特定し、調査の方向性を提示 4. ドメイン知識の問合せ 請求情報と勤怠情報の連携で、過去にどんな問題が起きた? 特定の機能連携に関して、過去に発生した データ不整合のリスク や、それに対する 現在のシステム対応状況 を説明 今後に向けて 実運用はまだQAチームに閉じていますが、今後は広く展開し不具合データだけでなく、膨大なドメイン情報や社内の知見も取り込み、QAや品質に関するあらゆる「困りごと」の相談相手となるAIアシスタントに育てていきたいと考えています。 さいごに 本記事では、カイポケQAチームの生成AIを使った具体的な取り組み事例を紹介させていただきました。技術の進化を「絵に描いた餅」で終わらせず、品質活動に積極的に取り入れるモチベーションを持って日々業務に取り組んでいます。その他、GitHub CopilotやClaude Codeを使って、プロダクトコードやPRの情報からテスト観点を効率的に抽出する活動もトライしています。 私たちQAエンジニアは単にバグを見つけるだけでなく、プロセスのデザインやチームの知識を構造化したり、最新のテクノロジーを活用してプロダクト全体の品質を高める役割を担っていると考えています。そういった新しい技術を品質活動に取り入れることにワクワクし、試行錯誤できるモチベーションがある方を積極募集中ですし、一緒に仕事をしたいと思っています。 興味がある方は、ぜひカジュアル面談でお話ししましょう!!
この記事は株式会社エス・エム・エスAdvent Calendar 2025の12月11日の記事です。 qiita.com こんにちは、介護/障害福祉事業者向け経営支援サービス「カイポケ」のリニューアルプロジェクトでSREを担当 していた 加我 ( @TAKA_0411 ) です。 私事ではありますが、9月にSREチームからプロダクト開発チームへ異動しました。現在はEmbedded SREではなく、開発者としてKotlinを用いたバックエンド開発を主に担当しています。 これまでの私のキャリアはQA → インフラ → SREという流れで、アプリケーション開発の経験はほとんどありませんでした。そのため、自分のスキルを広げたいという思いから挑戦させてもらっています。 当初はIntelliJのセットアップやDDDの理解などに苦戦しましたが、チームメンバーの多大なサポートもあり、ようやく少しずつ慣れてきたと感じています。 前のチームでの私は「どのようにオブザーバビリティを実現・高めていくか」ということに注力していたのですが、実際に開発チームで動いているうちにオブザーバビリティに関する考え方や取り組みに関して新しい視点が芽生えてきたと感じているので紹介します。 きっかけはいつもカンファレンス まず、私にとってひとつの転機となったイベントを紹介します。2025年10月27日に開催されたObservability Conference Tokyo 2025です。 o11ycon.jp このカンファレンスはオブザーバビリティという技術領域にフォーカスしたイベントで、ロール・文化・運用・OpenTelemetryなど幅広いテーマが扱われていました。弊社もロゴスポンサーとして協賛しています。 中でも特に印象に残ったのは、LINEヤフー株式会社のToshiya Katoさんによる「オブザーバビリティが育む開発者のシステム理解と好奇心」というセッションです。アーカイブ動画も公開されているので、ぜひご覧ください。 o11ycon.jp youtu.be このセッションは「オブザーバビリティツール、本当に使われていますか?」という問いかけから始まります。 サービスのテレメトリーデータを一通り揃えている しかし、テレメトリーデータが実際に活用されるシチュエーションはリリース時や問題発生時であった 問題発生時にはオブザーバビリティツールを用いたものではなくベテランによる解決というケースが起こっていた テレメトリーデータやオブザーバビリティツールが日常的に利用されているとは言えない状況 つまり、システムを理解するためのオブザーバビリティではなく、オブザーバビリティツールを導入してモニタリングしていただけでは?という状況であると整理されています。 このようなプロダクトやチームの状況をふまえ、メンタルモデルという切り口から下記のように課題を整理していました。 私たちはドキュメントやコード、ダッシュボードなどを通じてシステムの姿を思い描いている(≒メンタルモデル) メンタルモデルとシステムがズレると仕様の誤解や障害が発生する 担当しているサービスでは障害が少なかった反面、メンタルモデルのズレの修正を行う機会を得ることができなかった 開発者とSREとではメンタルモデルが異なっており、開発者はコードやドキュメントから、SREはダッシュボードなどのテレメトリーデータから構築している 上記のメンタルモデルの違いはDevOpsのサイクルと一致しているようである オブザーバビリティツールはDevOpsの "Ops" のサイクルで拡充されがちで、開発者にとっては使い慣れないツールになってしまう "Dev" のサイクルでオブザーバビリティツールを使うことでシステムの理解と好奇心を育てることができるのではないか DevOpsサイクル ( https://www.pagerduty.co.jp/blog/devsecops-cultural-transformation ) 上記の課題を解決するため、"Dev" のサイクルで本番同等の観測ができる環境と負荷が必要と考え、GitHubのPRごとのPreview環境、そしてカジュアルに実施できる負荷試験のシステムを整備した取り組みを紹介していました。 ここまでの発表内容から自分の取り組みを振り返ってみると、SREとしての私が注力してきたのは "Ops" のサイクルでのテレメトリーデータ拡充にすぎず、それこそ "オブザーバビリティツールでモニタリングをしているだけ" という状況に陥っているということに気付きました。これからの自分に必要なのは "Ops" のサイクルで得られた学びやフィードバックを適切に "Dev" のサイクルに取り込み、オブザーバビリティツールを活用してシステム理解を深め、問題をより迅速に解決できる環境を整えることだと強く認識しました。 このセッションが自分にとって大きな転換点となったこと、そして貴重な発表をしていただいたことを改めてToshiya Katoさんに感謝したいと思います。 オンコール対応から見えてきた課題 カンファレンスを経て意識が変化した直後の11月末、珍しくオンコール対応が必要なアラートを検知しました。私も開発者としてトラブルシューティングに参加しました。 DatadogのAPMを見つつエラーの箇所を追っていくと、DatadogのGitHub Integrationが役立ち、問題箇所と原因を早い段階で把握できました。しかし、実際にどのようなリクエストが送られているのか、なぜそのようなリクエストが送られてしまったのかといった調査にとても手間取ってしまいました。 また、Slackに通知されたアラートメッセージが抽象的だったこともあり、そのアラートを見て我々がどのようなアクションが必要なのかという点で初動の遅れに繋がってしまいました。 12月3日の記事 にあるとおり、私たちが開発しているカイポケのシステムは分散システムとなっています。WebフロントエンドからAPIのGatewayを経由するデータや、コンポーネント間の通信データもあります。そのため、オブザーバビリティの考え方としては問題を引き起こしたデータがどこから来たのか、その中身が何であったのかを収集しておいてすぐに確認できる状態であるべきでした。 システム概要図 また、私を含め開発者がトラブルシューティングのためのDatadogの利用に不慣れであったり、オンコール対応のためのRunbookがまだ整備されていないという状況でした。最終的には開発経験が長く詳しい人にデータを調査をお願いし、事なきを得てひとまず落ち着きました。これはつまり下記の状況です。 問題発生時にはオブザーバビリティツールを用いたものではなくベテランによる解決 システムを理解するためのオブザーバビリティではなくツールを導入してモニタリングしていただけ 開発者にとっては使い慣れないオブザーバビリティツール このような状況を踏まえ、同じチームの同僚と簡易的なポストモーテムを実施し、現状の課題を整理しつつ迅速なオンコール対応を可能にするための改善を進めています。プロダクト開発チームに所属することで私に当事者意識が芽生えたのでしょうか、チーム全体での "開発者が自分たちの手で観測・理解できる環境づくり" への意欲が高まっています。"Dev" のサイクルでオブザーバビリティツールを使うこと、それに慣れること、そしてシステムの理解を深めることの重要さを痛感しました。 まとめ 今回のチーム異動とObservability Conference Tokyo 2025への参加を通じて、オブザーバビリティへの理解が大きく変化しました。 今後はより開発サイクルに密着した実践的なオブザーバビリティ改善を進めていきたいと思います。 社内で「オブザーバビリティ・エンジニアリング」の輪読会を開くなど、私の所属チーム以外でもオブザーバビリティへの関心が広がりつつあります。 今回の改善でどのような成果が見られたのかについては、結果が出次第またブログや登壇で共有する予定です。今後の報告もぜひご期待ください。
この記事は 株式会社エス・エム・エス Advent Calendar 2025 の12月9日の記事です。 はじめに ちょうど1年ぶりのテックブログへの登場となりました。BPR推進部EA推進グループでエンジニアをしている、おうえ @kotaoue です。 この記事は「エス・エム・エスに入社してから、楽しく仕事をするためにおうえがやってきたこと」を振り返ってみようという、個人的な想いドリブンで書いています。 ※ 同時に「BPR推進部ってどんなチーム?」や「エス・エム・エスのBPR推進部でエンジニアとして働く楽しさ」みたいなものを、もしかして将来一緒にチームとして仕事をすることになる誰かに伝わると本当に最高だなという期待も結構込めています! 具体的なTechの話というよりは、開発フローやカルチャーに関するポエムです。 簡単な自己紹介 まずは、おうえの略歴を簡単に書いておきます。 これから「エス・エム・エスのBPR推進部でエンジニアとして働く楽しさ」に触れますが、それは「ただしこんな感じで仕事をしてきた人にとって」という前提が付く話にはなるので略歴を書いておきます。 20年以上前に就職してから、ゲームプランナー → 起業試みて失敗 → Slerでプログラマ → 事業会社の社内SE → ゲーム会社のサーバーエンジニア → SaaSスタートアップのエンジニア といった感じで仕事をしてきています。 ちょっと変則的なキャリアプランで参考にならないよと思われるかもですが… 「Slerのプログラマ」「個人事業主」「スタートアップのメンバー」のような何個かの視点から語っていると感じていただけると幸いです。 BPRって何? EA推進グループって何? エス・エム・エスには「プロダクト開発部」とは別に「BPR推進部」という組織も存在します。 そこで、 昨年の記事 と同様に、所属している部署の紹介を記載しておきます。 まず、BPR推進部ですが、BPR(Business Process Re-engineering)の略称です。 とても簡単に言うと「部署を横断して会社全体の業務プロセスを改善していくこと」が目標のチームとなっています。 ちなみに、EA推進グループは、EA(Enterprise Architecture)の略称で、ここにも「ビジネス戦略とITを統合してシナジーを最大化していこう」といった想いが入ったチーム名となっています。 「プロダクト開発部」と「BPR推進部」では、お互いに「マーケット(市場・業界)へ向けて」価値を届けるという方向性は同じですが、そこへ至るアプローチとして、主に以下のような役割分担をしています。 プロダクト開発部⇒マーケットに向けて直接価値提供するサービスの開発・提供 BPR推進部⇒マーケットへのサービスデリバリーまでを含めた社内の業務プロセス改善/業務システム構築 もちろん、この役割分担も固定的なものではなく、お互いにやるべきと思ったことをオーバーラップしたり協業したりしながら組織横断的に成果に向かって動いています。 ※ このTechBlogも、プロダクト開発部とBPR推進部の両方のメンバーがエントリーを書いて運営しています。 テーマとしていた働き方の発表 規模としては多くの従業員数が所属するいわゆるエンタープライズ企業ということで、エンタープライズ企業ならではの働き方が必要だと入社前から少し身構えていました。 例えば、組織として守るべきルールや、登場人物が多いことによる調整の難しさや独特のスピード感については、前職のスタートアップとは大きく異なると想像していました。 そんな組織の中で、自分として楽しく仕事をする&組織に価値を還元できるように、「とりあえずやってみる」を自分のテーマにしてきました。 ※ 裏テーマは「誰かに怒られるまではやってみる」でした。 それは、これまで主に「Slerのプログラマ」「個人事業主」「スタートアップのメンバー」として働いてきた人間が「エンタープライズ企業」でプレゼンスを示すためには、ちょっと違った視点ややり方が大事だと思って作成したテーマです。 その一例として「自分の好きな仕事」について部全体に共有会を実施することになった件を紹介します。 「自分の好きな仕事」について部全体に共有会を開催することになった件 おうえはポストモーテムが大好きです!色々ある仕事の中で一番好きだと言っても過言では無いです。 そして「楽しく仕事をしたい」し「とりあえずやってみる」「誰かに怒られるまではやってみる」がテーマの一年だったので、「よし、ポストモーテムの魅力を伝える共有会をみんなに向けて開催しよう」と動いてみた結果の振り返りです。 開催までの流れ 共有会を開催したいなと思う 「ポストモーテムが大好きなので、ポストモーテムの魅力を伝える会を開催したいです!参加者募集です」とSlackのBPR全体チャンネルに投稿 実際のメッセージのスクリーンショットは↓ 部長から「何より楽しいっていうところが良いですね!」というコメントを貰って喜ぶ 開催 という感じでした。 入社前に身構えていたエンタープライズ企業的な難しさもなく、「やりたい」→「いいね」→「やる」という軽いフットワークで開催することができました。 また、個人の思いつきが起点となった共有会ですが「一緒に内容ブラッシュアップしよう」とマネージャーも前のめりで協力してくれるなど、とても動きやすい環境でした。 この時点で「BPRという組織は、入社前に想像していたよりも数倍〜数十倍の裁量範囲がある」ということを感じ、それは「誰かに怒られるまではやってみる」という限界を攻めるのも難しいなという、大きな驚きになっていました。 開催した結果 結果として、共有会の冒頭に表示されるスライドで「好きだから」を全面に押し出すような、個人的な想いが満載の共有会を開催することになりました。 反応も上々で 共有会を聞いて、3秒後にesaでポストモーテムを仕組み化、チームのドキュメントとしてシェアしました! さっそくチームでポストモーテムやってみました!再発防止策はみんなで考えようぜ!という意識で議論できたのは良かったと思います! 経営管理本部とか他部署のメンバーにも共有したいなぁと思うんですけど、エス・エム・エス全体に広げちゃってもいいですか? といった感じで、BPRの中で反応するだけではなくて他部署にも波及するという、当初抱いていたエンタープライズ企業という想像を打ち砕くような軽やかな結果となりました。 ポストモーテムが好きな理由の補足 今回の記事は「楽しく仕事をするためにテーマとしていたことの振り返り」なので、ポストモーテムについては深堀りしないようにしようと思いましたが、やはり好きなのでちょっとだけ語らせてください。 ポストモーテムが好きな理由は「 ポストモーテムを楽しめるメンバーの集まったチームが好きだから 」です。 そしてその理由を細分化すると ポストモーテムが好きってことは、失敗しても批判されないし、失敗からポジティブな学びを得るチーム 失敗からポジティブな学びを得るってことは、新しいことにチャレンジできるチーム 新しいことにチャレンジできるってことは、もっと良いチームになる可能性が高いチーム もっと良いチームになる可能性が高いチームってのは、参加していて楽しいチーム! という感じです。 そして、共有会を開催するまでの流れで「 自分が参加しているチームはもっと良いチームになる可能性が高いと感じることができた 」というのが最高のフィードバックでした。 まとめ 入社前にはエンタープライズ企業だからと身構えていましたが…実際には「やってみたいな」と自分からアクションを起こせば、やってみたい仕事にチャレンジできる機会がある、拍子抜けするくらい軽いフットワークで色々なことができる組織でした。 「はじめてのポストモーテム」だけではなく「LT大会やってみませんか」「輪読会やってみませんか」「プロダクト開発で実施しているボードゲーム会に参加して良いですか?」といったチームカルチャーにまつわる相談にはもちろん「やってみよう」という反応で進行することになりました。 また「ダッシュボード作りましょう」や「AIエージェント使ってみたいです」や「次はJavaじゃなくてGoでPoCやりたいです」といった技術的な希望や「ITGCの統制対象となっているシステムの開発フローだがやりづらい部分があるので変更したい」といった開発フローやIT全般統制に関わるようなややこしい要望であっても、一度も「NG」と言われることがない組織でした。 他にも「ちょっと1on1したいです」とSlackで声をかければ、技術責任者の田辺さん( @sunaot )とも1on1実施できるという、スタートアップのようなとても距離の近いコミュニケーションも可能な組織でした。 もちろん「とりあえずやってみよう」ではなくて「それをやるためには情報を整理して然るべきルートで承認申請してから」といった進め方になることはあります。 それでも「じゃあどうすれば実現できるか」という視点で動けるのが、BPR(Business Process Re-engineering)という言葉が入った組織の強みであり、エス・エム・エスという会社の社風なんだなと感じたのが、一年を振り返った率直な感想です。 さいごに アドベントカレンダーの中ではありますが…BPR推進部では一緒にエス・エム・エスのBPRに取り組んでくれるメンバーを募集中です。 BPR推進・コーポレート エンジニア職種一覧 としてまとめております。 もちろん「とりあえず、1回話をしてみたいなー」というカジュアル面談も大歓迎なので、↓にあるカジュアル面談のリンクをクリックしてみてください。 また、BPRについてもう少し知りたい方向けへの記事もリンクしておきます。 規模はエンタープライズですが、スタートアップ的な速度感で動くことのできる組織なので、「チャレンジしがいのある大きなissue」がたくさんありますし、ぜひ一緒にチャレンジしたいと思っていますという想いを伝えて筆を置きます。 もうすこしBPRについて知りたい方向けへの記事 組織のやっていることを知りたい方へ 多様なビジネスモデルを展開している成長企業のBPR組織のミッション BPRらしさの詰まったビジネスアーキテクトという職種について知りたい方へ ビジネスアーキテクト × Salesforce:改善だけで終わらない、戦略推進と戦術実行を追求する その他、BPRメンバーの書いた記事は こちら
この記事は株式会社エス・エム・エスAdvent Calendar 2025の12月8日の記事です。 qiita.com プロダクト開発部 人材紹介開発グループの田実です。 人材紹介サービスは今年から Career Portal という新しい社内基盤を開発・運用しています。 本記事ではこのCareer Portalの概要や利用技術について紹介したいと思います! 人材紹介サービスの課題とCareer Portal エス・エム・エスでは医療・介護・保育などの領域で人材紹介サービスを提供しています。 人材紹介サービスは「キャリアパートナー」と呼ばれる、従事者(求職者)と事業者を繋ぐ転職・採用支援担当が双方とコミュニケーションをとり、より良いマッチングを創出しています。 より良いマッチングを提供するために、昨年末からキャリアパートナーにご協力いただきキャリアパートナーの全ての業務プロセスをヒアリングしました。 業務プロセス理解の取り組みに関しては以下の記事でも紹介しておりますので、こちらも読んでもらえると嬉しいです! tech.bm-sms.co.jp ヒアリングした業務プロセスを一部抜粋したものが以下になります。 ご覧の通り、キャリアパートナーの業務は非常に多岐に渡り業務量がとても多い状態でした。センシティブな情報を扱ったり不確実性が高い業務も多く、タスクの質・量ともに負担が大きい状況でした。 また、情報の粒度やストア先、コミュニケーションツール、ノウハウなどが各チームや個人で異なっているといった課題もありました。 このヒアリングを通じて より最適なマッチングを提供するためには業務プロセスの見直しや業務システムの改善を行う必要がある ということが改めてわかりました。 これらの課題を解決すべく、今年から開発チームが主体となりプロジェクトを発足しました。 このプロジェクトで作った社内業務アプリケーションが Career Portal です。 1 ここからはこのCareer Portalの技術基盤について詳細を紹介していきます。 全体的な構成図 インフラはGoogle Cloudで構築しており、以下のような構成になっています。 ユーザー(キャリアパートナー)がLoad Balancer経由でWebアプリケーション( Cloud Run )にアクセスし、DB( Cloud SQL )からデータを入出力するような一般的な構成です。社内アプリケーションなのでLoad BalancerにはIAPによるアクセス制限も入れています。 Cloud SQLのデータは日次でBigQueryに連携しています。 Looker Studio からBigQueryに接続してダッシュボードを作成しており、データやGAから利用状況の確認・分析を行っています。 上記の構成図からは割愛していますが、バッチ処理もあり、Cloud Run Jobsのアプリケーションを Cloud Scheduler で動かしています。 VertexAI を使った生成AIの機能は別アプリケーションとして実装しています。生成AIのレスポンスは数十秒以上かかるため、Webから直接AIアプリケーションにリクエストするのではなく、 Cloud Tasks を使った非同期化やリトライ管理も行っています。 Celeryなどのジョブワーカーを利用する方法も案としてはありましたが、Career Portalリリース時点ではCloud Run Worker Poolsがパブリックプレビューだったことや、運用・保守の負荷の面を考慮しCloud Tasksを採用しました。 アプリケーションアーキテクチャ WebアプリケーションはTypeScript / Next.js を使って実装しています。認証は NextAuth.js 2 を使っており、社内GoogleアカウントのOIDCによる認証基盤を実装しています。ORMとして Prisma 、UIライブラリは shadcn/ui 、フォーマッタ・Linterは Biome 、テストは Vitest と最近よく見かけるような技術構成になっています。 AIアプリケーションはPython / FastAPI を使っています。パッケージ管理は uv 、型チェックは mypy 、フォーマッタ・linterは Ruff とこちらもPythonアプリケーションでよく見られる技術構成になっています。 バッチアプリケーションはNode.js (TypeStrippingを使ったTypeScript)で実装しており、CLIフレームワークとして Commander.js 、フォーマッタ・Linter・テストはWebと同じくBiome、Vitestを使っています。 リポジトリはインフラも含めてモノレポで管理しています。 ロギング 全てのアプリケーションで構造化ログを採用しています。 Webアプリケーションではロガーライブラリとして pino を使っています。開発環境ではコンソール上でJSON形式のログが見づらい問題があったため pino-pretty も使っています。 Pythonのロガーは標準のloggingライブラリを使ってJSON形式のフォーマッタを定義・適用しています。 class JsonFormatter (logging.Formatter): default_msec_format = "%s.%03d" def formatTime (self, record): dt = datetime.datetime.fromtimestamp(record.created, tz=JST) return dt.isoformat() def format (self, record): log_record = { "timestamp" : self.formatTime(record), "logger" : record.name, "level" : record.levelname, "levelno" : record.levelno, "message" : record.getMessage(), "args" : record.args, "created" : record.created, "context" : { "pathname" : record.pathname, "module" : record.module, "funcName" : record.funcName, "lineno" : record.lineno, }, } return json.dumps(log_record, ensure_ascii= False ) def getLogger (name: str ) -> logging.Logger: logger = logging.getLogger(name) handler = logging.StreamHandler() handler.setFormatter(JsonFormatter()) logger.addHandler(handler) CI/CD CI/CDはインフラも含め全てGitHub Actionsで行っています。GitHub Actionsのアクションは pinact でpinningしており、 actionlint によるワークフローファイルの静的解析も行っています。Google CloudのAPIにアクセスする場合は Workload Identity連携 を使ってGitHub Actionsから認証しています。 CIの内容としてはWeb・バッチは Biome・tsc・Vitest、AIアプリケーションではRuff・mypy・pytest、インフラでは tflint ・terraform fmt・ trivy によるチェックを動かしています。さらに、 lefthook を使ってローカル環境でコミット・プッシュする前にLinter・フォーマッタを動かして対応漏れを防いでいます。 アプリケーションの自動デプロイは mainブランチへのデプロイ => 開発環境への自動デプロイ GitHubのリリースを切る => 本番環境への自動デプロイ としています。 production用のブランチを切って運用する方法もありましたが、その分プルリクエストやブランチが増えて管理性が悪くなるデメリットもあったので、Career PortalではGitHubでリリースを切る方式を採用しました。 mainブランチにマージして開発環境での動作確認した後は速やかにリリースする、といった開発・本番環境の乖離が発生しづらいフローを想定していたというのも理由の1つです。 GitHubのリリースを手動作成するのも面倒なので、mainブランチにマージしたらDraftリリースを自動で作成し、そのリリースをPublishするだけで自動デプロイができる仕組みも実装しました。 DraftリリースのリンクはSlackに通知しているためDraftリリースのリンクを探す手間も無くなるようにしました。 o11y インフラのメトリクスをDatadogのダッシュボードで閲覧できるようにしたり、メトリクスが閾値を超えたらSlackに通知するような仕組みも実装しました。 Sentryも各アプリケーションに実装しており、予期せぬ不具合が発生した場合はSentry経由でSlackに通知されます。 RDBの特定のデータを監視して異常がないかどうかの確認もバッチ処理で実装しています。 MetabaseやRedashなどのBIツールを使ってデータを監視・通知する方法も実装案にあったのですが、総合的な実装・運用コストがバッチによるスクラッチ実装のほうが少ないと判断しました。 BIツールという観点だとアドホックなクエリを打てる環境が運用上求められることがありますが、こちらはCloud SQL Studioで対応しています。Cloud SQL StudioだとGoogle Groupを使ったIAM認証が利用できるため、クレデンシャル管理せずにデータアクセスができて非常に便利です。 検証環境 ローカル開発環境では検証しきれないため、本番相当のインフラ構成である検証環境も構築しました。 検証環境はプルリクエストごとに作成できると良かったのですが、IAPやCloud Storage、Eventarcの設定など純粋にアプリケーションの分離だけでは設定が不十分になってしまうことや、実質的に5つ程度の環境があれば十分開発が回る体制だったため、事前に構築した検証環境を各開発者に提供する形にしました。 Cloud Runはリクエストされていないときにコンテナを停止できて、コールドスタートも開発検証する上では許容範囲だったため、コスト的な心配や開発体験の影響もなく安定して運用ができています。 その他 Renovateによる定期バージョンアップ Renovateによる定期バージョンアップも行っています。各アプリケーション・依存グループでグルーピングされたプルリクエストが週次で作成されるように設定していて、CIが通っていて動作確認上も問題なければ良きタイミングでリリースしています。 生成AIによる開発プロセス効率化 例に漏れず、弊社でも生成AIを活用し、開発プロセスをより効率的にしています。 具体的にはClaude Codeによるコード自動生成、GitHub Copilotによるコード補完、GitHub CopilotによるPRコードレビュー、Meetの録音からの議事録自動生成、Geminiによる設計の壁打ち・技術課題解決、NotebookLMによる情報整理・検索など、様々な業務で活用しています。 初回リリース時は3〜4名で2〜3か月で構築していますが、生成AIの活用無しではこの人数・スピード感でのリリースは難しかったのではないかと思います。 ふつうの技術基盤を作りたい 新しくアプリケーションを立ち上げたり、あるいは既存のアプリケーションの改善をする場合、「ふつう」な技術基盤を作ることを意識しています。 「ふつう」の水準はエンジニアのレベル感でだいぶ変わってくるのですが、自分にとっては シンプルなインフラ構成で シンプルなアプリケーション設計で ローカル開発環境はコンテナで用意されていて 本番相当の適切な検証環境も用意されていて テストがそれなりに書かれていて CI/CDも用意されていて インフラ・DBやログなどのメトリクスを閲覧したり異常を適切に検知できる環境があって インフラはIaCで管理されていて 分析できる環境が整っていて ライブラリは定期的にアップデートされて最新のものが利用できるようになっていて 開発プロセスも生成AIを適切に使っている みたいな基盤です。 「ふつう」な技術基盤にすることで考えることを少なく・シンプルにして技術的な運用負荷を減らし、結果として、業務・ビジネスの課題解決によりフォーカスできるようになることを期待しています。 これら全てをやるにはそれなりの経験が必要ですが、ブログ記事などWeb上にサンプルコードのような「答え」を見つけるのが比較的容易な領域とも言えます。 今だと生成AIを使えば壁打ちしながらすぐに実装できるかもしれません。 結局コツコツと基盤を改善していくしかなく、この辺がサクッと導入できるくらいのスキルや経験も積み上げていくしかないのかなぁと思っています。 まとめ 社内業務アプリケーションのCareer Portalで使われている技術について紹介をしました。 Career Portalリリース後、「業務負荷が下がった」「最適なマッチングを提供できた」というポジティブなフィードバックを多くいただいています。 今後も業務理解・整理・システム改善を繰り返し、従事者と事業者の最適なマッチングを通じて 医療・介護/障害福祉の人手不足と偏在の解消 3 を目指していきたいと思っています。 既存の業務システム基盤は、今後の機能追加や事業の変化に対応し続けることが困難だったため、システムを切り離して新たに実装しました。 ↩ ぼちぼちBetter Authに切り替えようかなぁと思ってます。 ↩ https://www.bm-sms.co.jp/service/career/ ↩
こんにちは、プロダクト推進本部人事のふかしろ( @fkc_hr )です。 11月21日と12月4日に開催された、プロダクトマネージャーカンファレンス 2025(pmconf 2025)にエス・エム・エスはSilver Sponsorとして協賛しました。また、カイポケSaaS部部長の川合とカイポケアーキテクトの三浦が登壇の機会をいただきました。この記事では、発表資料とともに登壇機会をいただくために行った工夫をお伝えいたします。 それぞれの発表タイトル・要旨・資料は以下のとおりです。 大阪会場 The Modelの罠を超える!売上9割"SLG"のVertical SaaSが挑む「PLG × SLG ハイブリッド戦略」 プロダクト・レッド・グロース(PLG)はバズワード化する一方、複雑な業務ドメインを扱うVertical SaaS、特に強力なセールス組織を持つ企業にとって、その導入は決して平坦な道のりではありません。むしろ、既存のセールス・レッド・グロース(SLG)との衝突や組織間の壁が、変革の大きな足枷となることもあります。 本セッションでは、売上の9割をセールス組織が担う介護SaaS「カイポケ」を事例に、私たちが挑んだPLGとSLGの「両利き」を目指すハイブリッドGTM戦略のリアルをお話しします。 「PLG ONLYは幻想」と割り切り、現実的なスコープを見極める方法 。The Model型組織における部門間の壁を乗り越え、プロダクトがGTMに貢献できる具体的なポイントをオンボーディング体験のリサーチから見つけ出したプロセス など、成功譚だけでなく泥臭い失敗談も交えて共有します。 ( セッション内容紹介 より) speakerdeck.com 東京会場 マルチプロダクトのカオスを制す。「プロダクトディシジョンレコード」で実現するチーム横断のアラインメント戦略 「なぜこの機能が?」「あの決定は誰が?」マルチプロダクトで並行開発するからこそ頻発する“意思決定の迷子”に悩んでいませんか? 私たちの組織も、プロダクト間での連携がうまく進まずカオスに苦しんでいました。この状況を打破すべく導入したのが、意思決定の背景と結果を記録する「プロダクトディシジョンレコード(PDR)」です。 本セッションでは、なぜPDRが必要だったのかという背景から、私たちが実際に運用しているテンプレート、導入プロセスで直面した「書くのが面倒」「何を書けばいいのかわからない」といったリアルな壁、そしてそれを乗り越えて得られた「納得感のあるアラインメント」と「自律的なチーム」への変化を、具体的な事例と共にお話しします。明日から使えるPDRのフォーマットと、組織に定着させるための実践的なヒントを持ち帰っていただけます。 ( セッション内容紹介 より) speakerdeck.com プロポーザル提出までの流れ 今年度は人事中心ではなく、各領域のコミュニティに近いメンバーが協賛関連の検討・企画・準備をしていました。その際にPdM陣が行っていたプロポーザルを提出するまでの取り組みや工夫についてご紹介します。 傾向分析 セッション応募すること自体がはじめてなメンバーも多かったこともあり、採択されるにはどうすればいいか?から検討していました。 公式から出ている募集要項や概要、昨年度のレポート、pmconf2025kickoff動画も参考に登壇テーマの分類や参加者属性、メッセージの内容などをまとめていました。 例えば、今回の登壇セッションは以下の8つのテーマに分類されていました。 プロダクトデリバリー プロダクトディスカバリー プロダクト戦略 事業戦略 Go To Market 意思決定とアライン 価値の検証と学習 組織戦略・キャリア・役割分担 その中でもプロダクトのフェーズからターゲットにしやすいテーマを複数にしぼることで、話しやすいテーマ出しにつながりました。 10件のセッション申し込み 気づいたら決まっていたのですが、セッションを10件出すという目標を掲げ、早々に「pmconf 公募セッション申込進捗状況」というスプレッドシートで管理されていました。定期的に検討している件数や申込締め切りをウォッチしていました。 結果として、PdMのみならず、開発部長や事業部長も提出しており、チームが珍しく期日ドリブンで動いていて、お祭りのようでした。 頼れる「Gemini のGem」の活用 いざセッションへ申し込もうと思っていても、登壇の全体像が完璧に見えてから提出できるわけではありません。そこで活躍したのが、壁打ちやプロポーザル提出の文章の叩きを作ってくれるプロンプトでした! ぼんやりとタイトルやテーマが決まっているが、まだ内容を作りきれていないというときに大活躍でした。 プロポーザルの提出までの試行錯誤が格段にしやすくなり、なんとか10件申請にたどり着くことができました。Gem&プロンプトを作ってくれた方に大感謝です。 結果相対的に通過率が高い取り組みに 結果としては、10件の申請中、2件採択いただきました。 ちなみに、pmconf の発表によると、応募数は323件、採択数は34件で、倍率は10倍とのことでした。比較すると、私たちの取り組みは相対的に通過率の高い結果となっています。 おわりに イベントの運営本当にありがとうございました。 また、川合さんの登壇レポートは、別途noteでも発信する予定です。ぜひチェックしてください。 来年のpmconfで、皆さんとお会いできるのを楽しみにしています! 発表内容やPdMの取り組みについてより詳しく聞いてみたいという方は、 ぜひカジュアル面談にお越しください!
この記事は株式会社エス・エム・エスAdvent Calendar 2025 vol.1の12月4日の記事です。 qiita.com エス・エム・エスで全社SREというロールで活動しているSecurity Hub芸人の山口( @yamaguchi_tk )です。おすすめのAWSサービスは営業です(いつもお世話になっています)。 はじめに 私が所属している全社SREチームで監視基盤の入れ替えを行った際、そのタイミングで監視設定自体も見直しました。 その見直しの中で、 脅威モデリング の考え方をインフラレイヤーの監視設計に応用して整理を行いました。 本記事では、そのときに実施した手法をできるだけ具体的に言語化し、同じように監視を見直したい方の参考になることを目指して紹介します。 背景 オンプレからAWSにLiftした際にオンプレと同じ構成でAmazon EC2を構築し、監視もZabbixを利用してオンプレと同じ構成で構築しました。 Zabbix自体のアップデートやAmazon EC2、Amazon RDSのアップデートを何度か実施した結果、アップデートの検証工数やZabbix自体の運用工数が課題になってきたため、フルマネージドサービスであるAmazon CloudWatchへの移行を行いました。 監視設定の整理の目的 監視設定自体はZabbixの基本テンプレートをベースに一部をカスタマイズして利用しており、特にメトリクスベースのアラートがシステムの実態と合っておらず 無駄なアラートが発生している 状況でした。 無駄と判断した監視設定は、発生のたびに削除したり閾値や監視するメトリクス自体を見直ししたりしていましたが、発生都度の対応ではどうしてもいたちごっこになってしまいます。 そこで、Amazon CloudWatchへの移行を機に方針を決めて監視設定を整理することにしました。 インフラレイヤーの監視設定への応用 インフラレイヤーの監視設定に脅威モデリングの手法を応用できないか検討し、実際に行ってみました。 これは古典的なセキュリティ原則の「可用性(Availability)」にフォーカスして脅威モデリングを実施した、と言えるかもしれません。 脅威モデリングについて 脅威モデリング(Threat Modeling)は、システムやアプリケーションのセキュリティを設計段階から考慮するための手法です。 アダム・ショースタック氏の以下のフレームワークが有名です。 Shostack’s Four Question Framework for Threat Modeling 何に取り組んでいるのか? What are we working on? 何が問題を引き起こす可能性があるか? What can go wrong? それに対して何をするのか? What are we going to do about it? 十分によい対応をしたか? Did we do a good job? 具体的には、DFD等でシステムの構成要素を可視化し、「起こったら困ること」という視点で脅威を特定します。 特定した脅威をSTRIDE等でカテゴリ分けし、その発生確率をアタックツリーで分析し影響度と併せてリスク評価することで、セキュリティリスクを事前に把握し、適切な対策を検討することができる手法です。 実施手順 ここからは、実際に行った手順を紹介します。 発生したら困ることを洗い出す まず、AWSの構成図を作成します。 1つ目の構成図(EC2版)には、オンラインWebサービスと同じインスタンスで処理されるバッチ処理が含まれています。 2つ目の構成図(AWS Fargate版)には、オンラインWebサービスとバッチ処理、非同期処理が含まれています。 AWSの構成図を見ながら、 起こったら困ること を基準に付箋などを張ったりして洗い出していきます。 例示したAWSの構成図の場合だと、以下のようになります。 オンラインサービス系 オンラインサービスが応答しない オンラインサービスの応答が遅延している バッチ系 バッチが処理されない 非同期処理系 非同期処理が処理されない 非同期処理が遅延している 処理フローを可視化する 洗い出した 起こったら困ること に対して、その処理(オンラインサービス系/バッチ系/非同期処理系)がどのようなシステムフローで実行されているかを、AWS構成図ごとに可視化していきます。 作成したAWS構成図から必要な処理フローを抜き出して構成します。 以下に上で例示したAWS構成図での可視化例を示します。 オンラインサービス系(EC2) バッチ系(EC2) オンラインサービス系(Fargate) バッチ系(Fargate) 非同期処理系(Fargate) 発生要因を分析する 洗い出した 起こったら困ること に対して、処理フロー図を見ながらその発生要因を抽象度高めで洗い出していきます。 ここでは「xxxというエラーでyyyが発生して処理が異常終了する」という詳細な記載ではなく、「処理が正常終了しない」といった抽象度高めの粒度で洗い出しを行います。 洗い出した例を図で示します。 オンラインサービス系発生要因(EC2) バッチ系発生要因(EC2) オンラインサービス系発生要因(Fargate) バッチ系発生要因(Fargate) 非同期処理系発生要因(Fargate) 直接的に監視できるところを探す 分析で洗い出した発生要因に対して、 一番直接的に観測できる箇所・監視内容 や、 処理の急所(ここを監視すればシステムフローの下流の異常が検知できる箇所・監視内容) を処理フローから探します。 洗い出した例を図で示します。 オンラインサービス系監視ポイント(EC2) バッチ系監視ポイント(EC2) ハートビート系処理でログを監視する場合は、ハートビート系処理をどこで動作させるのか、バッチ処理のログをどこに出力するのか、といった点もあわせて考慮する必要があります。 オンラインサービス系監視ポイント(Fargate) バッチ系監視ポイント(Fargate) 非同期処理系監視ポイント(Fargate) バッチ系監視ポイント(Fargate)では、以下の理由でAWS Step Functions以降を監視することで全体をカバーしています。 Throttlingが発生する可能性がある場合は通常Amazon SQS等を挟むため、このシステムはThrottlingが発生する状況になることは少ないと考えられる。 Amazon S3とAmazon EventBridge間でThrottlingが発生してもAWS Step Functions自体は起動することを期待している。 Amazon EventBridgeの定時処理は少なくとも1回は起動することを期待している。 まとめ 監視設定の整理に脅威モデリングの手法を応用することで、以下の効果が得られました。 システムの実態に合った 最低限必要な監視設定 が可能になります。 「起こったら困ること」を起点にすることで、無駄なアラートを削減できます。 処理フローを可視化することで、監視ポイントの選定根拠が明確になります。 この手法は既存の監視設定の見直しだけでなく、新規システムの監視設計にも応用できると考えています。
この記事は株式会社エス・エム・エスAdvent Calendar 2025 12月3日の記事です。 qiita.com 介護/障害福祉事業者向け経営支援サービス「カイポケ」のソフトウェア開発者の空中清高(@soranakk) です。 本記事ではカイポケのバックエンド開発で取り入れている、スキーマからのコード生成に焦点を当てて取り組みや工夫を紹介したいと思います。 カイポケのシステム概要 まずはこちらの図をご覧ください。 こちらはカイポケのシステム概要図となっています。 バックエンドにはいくつかのサーバーが存在していて、それぞれのサーバーはGraphQL APIを公開しています。 そして、それらをGatewayで1つのGraphQL APIにまとめて、フロントエンドに公開しています。 またそれぞれのバックエンドはSpring Bootで構成されていて、KotlinとSpring for GraphQLを利用して開発しています。 さらにそれぞれのバックエンド毎にデータストアとしてPostgreSQLのデータベースを持っている構成になっています。 本記事ではこれらのバックエンド開発のコード生成に焦点を当てて紹介したいと思います。 コード生成を利用している箇所 コード生成は主に2箇所で利用していて、1つ目はGraphQL Schemaからのコード生成です。 それぞれのバックエンドで公開しているGraphQL SchemaからKotlinのコードを生成して利用しています。 もう1つはデータベースアクセスでPostgreSQLのスキーマからKotlinのコードを生成して利用しています。 GraphQL Schema からのコード生成 カイポケのバックエンドではSpring for GraphQLを利用してGraphQL APIの開発をしているのですが、Spring for GraphQLにはコード生成の機能が存在しません。 そのため、カイポケではDGS Framework (Domain Graph Service)というライブラリのコード生成を利用しています。 DGS frameworkはNetflixが提供している、Spring BootでGraphQLを開発するためのライブラリです。 リンク: https://netflix.github.io/dgs/ DGS frameworkにはコード生成のためGradleプラグインが用意されていて、それを使うとKotlinのコードを生成することができます。 ちなみにSpring for GraphQLの開発においてコード生成でDGS frameworkを利用することは公式ドキュメントでも触れられていますので、半分ぐらい公式的な方法です。 リンク: https://docs.spring.io/spring-graphql/reference/codegen.html データベーススキーマからのコード生成 カイポケのバックエンドではjOOQというORMを利用してデータベースアクセス層の開発をしています。 jOOQにはデータベーススキーマからのコード生成プラグインが提供されているので、それを利用しています。 jOOQを使ったデータベースアクセスは、例えばソースコードはこのような感じになります。 by公式ドキュメント: https://www.jooq.org/doc/3.20/manual/sql-building/dsl-api/ val result: Result <Record?> = create.select() .from(AUTHOR) .join(BOOK).on(AUTHOR.ID.eq(BOOK.AUTHOR_ID)) . where (AUTHOR.YEAR_OF_BIRTH.gt( 1920 )) .and(AUTHOR.FIRST_NAME.eq( "Paulo" )) .orderBy(BOOK.TITLE) .fetch() この時に利用するテーブル名やカラム名、View名やRecord型などがjOOQによって生成されたコードとなっています。 生成するときはデータベースのスキーマを直接参照して生成することになるので、DockerなどでPostgreSQLを起動しておいたり、 TestContainersを使ったりしてPostgreSQLを起動した状態でコード生成します。 コード生成のメリット:GraphQL GraphQLのコード生成によってリクエストやレスポンス型のdata classを自分で書く必要がなくなります。 これらはGraphQL Schemaに合わせて定型的な型を定義して利用するだけなので、コード生成できると楽です。 さらにGraphQL Schemaからコード生成されるため、GraphQL Schemaを修正すれば自動的にコードへ反映されるようになります。 そのためGraphQL Schemaを更新したけどコードへ反映が漏れていた、みたいなことにコンパイルエラーで気づくことができます。 ユニットテストやCIでも気づくことはできるのですが、やはり修正してすぐに手元のエディタで気づけるほうが開発者体験として良いです。 コード生成のメリット:データベース データベースのスキーマは何らかのマイグレーションツールを使って管理していると思います。 カイポケではgolang migrateというGo言語で作られたマイグレーションツールを利用しています。 リンク: https://github.com/golang-migrate/migrate こちらのツールではデータベースの更新をSQLファイルを使って管理します。 そのためデータベースのスキーマを管理するSQLとアプリケーションコードのKotlinで変更を同期しておかないと、データベースは更新したのにアプリケーションが発行するSQLは古いままでエラーになってしまう、みたいなことが発生しがちです。 そこでデータベーススキーマからコード生成することで、自動的に同期できるようになります。 なのでGraphQLの時と同じく、データベースを更新したけどコードが古いままになっていた、みたいなことにコンパイルエラーで気づくことができます。 CI での活用 スキーマとコードのズレにコンパイルエラーで気づける、という話をしましたがそれでも漏れてしまうこともあります。 そこでGraphQL SchemaやデータベースのマイグレーションのSQLが追加された時などをトリガーにしてCIでコードの自動生成を行なって、変更がコードに反映されているかどうかをチェックしています。 手元で修正漏れがあったとしてもPRのCIでチェックされるので、整合性が取れていない場合はマージされることもありません。 このような自動化が行えることも自動生成の利点だと思います。 まとめ 本記事ではカイポケのバックエンド開発で取り入れているコード生成に焦点を当てて紹介しました。 コード生成を活用することで外向けのインターフェースと内部のソースコードの整合性のチェックが自動化できたり、開発者がコンパイルエラーで不整合に気づけるというメリットがあります。 DGSのようにコード生成部分だけ利用するってケースもありかなって思っています。 また、本記事の内容はKotlin Fest 2025やJJUG CCC 2025 Fallのカンファレンスのエス・エム・エスのブースでも紹介していました。 ブースでは実際のソースコードも見せながら色んな工夫を話すことが出来たので、今後もエス・エム・エスのブースを見かけたら立ち寄ってもらえると嬉しいです。
この記事は 株式会社エス・エム・エス Advent Calendar 2025 の12月1日の記事です。 qiita.com  みなさんこんにちは。Analytics & Innovation推進部の井手です。あっという間に今年も12月。心の準備も済まぬ間にカウントダウンが始まる時期に突入です。そして今回の記事はAdvent Calendar 2025の記事の一つでありしかも1日目とのこと。華々しい幕開けとなれるかどうか。はてさて。 RecSys2025に参加してきました  前回の 私の記事 でも書きましたが、私は現在求職者と事業者に対してリコメンドを提供するシステムの作成に関わっています。そしてインプットの一環として、だいぶ過日となってしまいましたが、秋にチェコはプラハで開催された RecSys というリコメンドシステムの国際カンファレンスに参加してきました。開催地域である中央ヨーロッパの国々を中心に、アメリカ、中国、イギリス、フランスなど世界各国からリコメンドシステムに関わる研究者や実務者が集まり、研究が共有されました。また、Music, Travel, News, HRといったドメインごとのワークショップも開かれ、実用的な観点での学びも多分にありました。 今回のRecSys 簡単に前置き  あまりこの界隈に馴染みのない読者の方も多くいらっしゃると思いますので簡単に前置きをいれておきます。ここで言うリコメンドシステムとは、ECサイトではおなじみの「あなたへのおすすめ」と表示されて自動的に商品が提案されるような、過去のデータを利用してターゲットとなるユーザーの好みやニーズを推測し、それにマッチするアイテム(群)を抽出するシステムのことを指します。リコメンドアイテムを決定するアルゴリズムは「自分の行動と似た行動をとっているユーザーのパターンを参考に決定する」「自分が高評価したアイテムの中身と似たコンテンツのものを探し決定する」などのアプローチの側面があり、またそれらの側面から、クラスタリングアルゴリズムの適用、行列分解、ディープラーニングを利用した手法などを用いてアイテムの決定がなされます。特に最近は、精度や柔軟性の高さから、ディープラーニングを用いた手法が中心となっており、今回のRecSysの発表の傾向も同様でした。 ドメインごとにみたRecSys   RecSysでは様々なドメインでのリコメンドについて扱われていますが、ここでは大きく「リコメンドシステムが成熟してきているドメイン」と「新たなドメインへのリコメンドシステムの適用」という2側面で今回のカンファレンスの特徴をまとめてみたいと思います。 成熟してきているドメインでのリコメンドの深化  E-commerceや音楽、映画、オンライン広告など、すでにリコメンドシステムが多数のユーザーが利用するサービスに取り込まれ、アーキテクチャーの実績がすでにある分野では、エンベディングの頑健性や安定性を高める取り組み、あるいはリコメンド結果の多様性に焦点をあてている研究などが多かったように思えます。例えばMetaのスタッフを中心とした Zhengらの発表 では、広告表示のリコメンドに関連する課題を解決するための提案でした。SNSで表示される予定の広告は、量が膨大なのはもちろん、一方で表示される広告とそうでない広告の差が激しく分布が歪んでいたり、広告の入れ替わりが激しくIDドリフトが生じやすいなどの点でエンベディングが不安定になりやすい。それを解決するために、似た意味を持つ広告をクラスタにして情報を共有するSemantic IDを用いる手法を提案しています。  また、新規ユーザーのように、該当サービスにほとんど過去の情報を持っていない中でリコメンドを行うコールドスタート問題については、今回も複数の研究発表がありました。クロスドメインやマルチモーダル等、入力のバリエーションを増やすことで解決する提案が多かったように思え、これは近年の傾向と言えるでしょう。コールドスタート状態における情報の補完を、他ドメインあるいは他メディアで補完する場合、いかにそれらの情報を目標とするドメインで利用できるフォーマットに変換するかが課題となります。マルチモーダルの例だと、イメージ情報、または音声情報をテキストのエンベディングに変換するのは今までであればかなりハードルの高いタスクでした。しかしLLMが登場し、この部分をLLMが担うことで、ハードルが劇的に下がり各ドメインへの適用結果の報告がかなり増えてきました。LLMは適用が容易ですので、今後多くのドメインでコールドスタートのリコメンドの質が改善されていくことでしょう。 新たなドメインへのリコメンドシステムの適用  一方、リコメンドシステムを新たな領域に適用しようという動きも多く見られました。例えば Bereket らは、アートセラピーにおける、絵や音楽のリコメンドに関する手法。既存研究では絵の刺激に対するクライアントの反応からリコメンドのモデルを学習させていたところを、音楽のモデリングも含めた双方からのクロスドメインで行うという研究を報告していました。また、オンラインコースのリコメンドでは、受講者の興味をモデリングする手法が既にありましたが、これは受講者の興味がシフトしたタイミングを把握できないという欠点が指摘されてきています。この課題に対して両方を達成するためのモデルの提案が Li らによってなされ、その効果と有効性が主張されていました。こういった領域は今後しばらくは様々な側面からのリコメンドアーキテクチャが提案されていくなかで、徐々にデファクトの方法が定まり、現在のe-commerceの領域のように深化していくのだろうなという印象を受けました。  また、本のリコメンドに関する研究や実装はすでに珍しくなくなっておりますが、リコメンド対象を子供に限定し、さらに既存のリコメンドで前提となるプロフィール情報やインタラクションログなどが(privacy lawなどで)取得できないという制限された状況でのリコメンドエージェントを作成するという Hillら による発表は非常に目新しく、そして大変興味深かったです。子供の各年齢がどのような感情パターンを持つかをグルーピングしたものと、リコメンド対象の本を感情的側面でベクトル化したものでLLMをファインチューニングしてエージェントを作成するという手法で、その有効性を主張されていました。発表者は今後の課題点など挙げられており、確かに今後改善するポイントは多くあるのかもしれないとは思ったものの、それ以上に発表者(学生さんたちでした)の「子どもたちにもっとたくさん本を読んでもらいたい」という研究のきっかけとなったモチベーションは素晴らしく、とても魅力的な研究であるなと感じました。 個人的に特に気になった研究  どのドメインの発表も興味深く聞くことができたのですが、上記全体を通して一番印象に残った研究は、NetflixのZielnickiらによる、 Orthogonal Low Rank Embedding Stabilization というタイトルの発表でした。  実際のサービスでリコメンドシステムを運用するにあたり、日々更新されるデータからの再学習は避けては通れません。ただし、再学習を行うにあたっては計算負荷や、再学習されたモデルから生成されるエンベディングが今までのものと変化してしまうという問題が大きな課題となります。この再学習で生成されたエンベディングの計算負荷や不安定性に対し、QR分解とSVDを用いて次元を下げた後に、プロクラステス回転を行い前の行列に近づけるというアプローチを提案しています。彼らはNetflixの実際のデータ(基準日および基準日から数週間後の日)をこの方法で学習させ比較し、両者の間に強い類似度が生じていることを確認したと報告していました。  通常、あるモデルを利用して検索用のベクトルインデックスを構築している場合などは、再学習でモデルを作り直すと、インデックスも作り直すことになります。データが膨大な場合にはモデルの学習と合わせてかなりの時間がかかることになります。今回提案された方法は、モデル学習のみならず、軸をプロクラステス回転で過去の軸に合わせることでインデックスの作り直しを避けることができる(可能性がある)点で非常に魅力的で、参考になりました。 RecSys in HR  RecSysでは、メインの研究発表とは別に初日と最終日にワークショップがあります。ワークショップなので、メインの研究発表よりもさらに領域特化した感じのトピックになりますが、基本的には研究発表がメインという点は同じです。いくつか参加しましたが、ここでは本業であるHRに関するワークショップ(RecSys in HR)について簡単に紹介します。  今回の発表は7件ほどあったと思うのですが、AI(特に生成AI)が生み出すバイアスに注目する研究が多かった印象です。LLM登場直後の、ジェンダーや人種などに対する極端なバイアスではなく、文脈がより多様化した中でのバイアスが扱われていました。例えば、 Hoffmannらの発表 では、職業のマッチングについて、そのマッチングがどの程度適切かをLLMに評価させた際のバイアスについて報告していました。それによると、アラビア系国籍の人はヨーロッパ系国籍の人に比べて、経験が少ないことをより大きなペナルティと判断したなど、細かい部分にバイアスが見られたということでした。  このような、細かいところに見え隠れする小さなバイアスというのは、ときに誰かを大きく傷つける可能性があります。LLMが持つ数多くの偏りに常に注意深くあることは、とりわけ我々のような、数多くの人に利用していただくサービスにAIを適用しようと考えている者にとっては非常に重要なことです。  ワークショップの最後には組織内でAIを利用するリスクとその対策について、研究者、実務者、弁護士を含めたパネルディスカッションが行われました。そこでも話題の中心は、LLMが持つバイアスについてであり、バイアスについて注意深くあること、そしてバイアスがあることを前提としたレギュレーションを明確に敷いていくことは絶対に必要であるし、国際的な流れでもあるという話がなされていました。これは大変手間のかかる作業ではあります。ただ、今後AIを使わないという未来はないことを考えれば、いつかは絶対にやらなくてはいけないことです。私たちの準備はどうであるか、今一度考えるとてもいいきっかけになりました。 自身の領域を改めて考える  さて、こうやって今回参加したRecSysのメインカンファレンスおよびHRのワークショップを振り返り、改めて私が目下取り組んでいるテーマや領域について考えてみたときになにを強く思うかというと、やはりHR領域でのマッチング課題というのは、他ドメインのマッチング課題とは課題構造が少なからず異なるなということです。  HR領域におけるリコメンドは、多くの場合コールドスタート問題を抱えています。転職希望者のなかの多くは、転職をするのが初めての求職者です。そして転職が当たり前の時代になっているとはいえ、総回数はe-commerceなどにおける買い物などとは比較にならないほど少ない。つまり過去の履歴はあったとしてもかなり少ない。インタビューなどを通じて把握した、求職者のニーズだけを頼りに適切なマッチングを行っていく必要があります。また、リコメンドモデルを作成するのに利用する過去の求人情報は、ほとんどの場合現在はすでにありません。希望の求人が満たされた時点でなくなってしまいます。学習時に成立した求人と、類似した求人を探す必要が出てきます。すると、リコメンドされる求人は「現在の求職者さんと似たニーズを持つ人にマッチしたものと、似た求人」と、だいぶ誤差の範囲の広いおすすめになってしまう可能性があります。  また、求職者のニーズというのは、他領域のリコメンドにおける「好み」とは異なり、制約に近いニュアンスを持ちます。好みであれば、多様性で許容されるかもしれませんが、制約となるとより強い条件をリコメンドシステムに課すことになります。しばしばジョブマッチングは、問題構造をデートのマッチングのアナロジーとして取り扱われることもありますが、私はこの好みと制約の違いから、デートマッチングとも大きく異なると考えています。つまり、RecSysで発表されるような研究をはじめリコメンドに関する研究は世の中に数多くあるものの、HR領域への効果的な適用を考えていくと、領域特化して考えなくてはならない部分が多分にあるのではないかと感じるようになっています。参考になるもの、そして独自に考えなくてはならないもの、それをきちんと切り分けながら課題を設定し、解決していく必要があります。考えてみると割と当たり前のことなのですが、様々な領域の話を聞くと、この点が輪郭を持って浮き上がってきます。すごい大事なことなんですよね。その気付きも含めて、実りの多いカンファレンスでした。  RecSysへの参加、自分ではもちろん意義があることだと思っていたけど、それをうまく伝えられるかなーなんて少し不安に思っていたのですが、上司である田辺さんに相談したところ、快諾してくださいました(勉強だけじゃなくせっかくだから楽しんできてください!とまで言ってもらえました)。自身の成長の背中をぽんと押してくれるのは、田辺さんはもちろんこの会社全体の文化なんだなあと大変ありがたく思っています。  というわけでこの経験を成長につなげ、日々の仕事に還元してまいります。求職者、そして事業者が最も欲しているリコメンドができるよう、引き続き精進していきます。 皆さんにも「いいものができたよ!」と報告できる日を楽しみに、アドベントカレンダー2日目にバトンを渡したいと思います。それではまた!!
こんにちは、 豊濱 です。 現在は、プロダクト開発部で ウェルミージョブ 、 シカトル 、 カイゴジョブアカデミー のエンジニアリングマネージャ(EM)を担当しています。 この記事では、現在ウェルミージョブで取り組んでいることについてご紹介します。 少し自己紹介 まだ20世紀だったころにソフトバンクに入社し、2日目に子会社のヤフーに出向ののち正式に転籍、そこから約16年働いていました。 21世紀に入ったあたりから、インターネットの急速な普及、大容量回線によるコンテンツの進化、スマートフォンの台頭など、業界や市場の成長とともにエンジニアとして自分も成長させてもらったな、運が良かったな、と今でも思います。その後、Web/IT系の企業に何社か転職、テックリード・アーキテクト・CTOなどを経験し、2024年にエス・エム・エスに入社して今に至ります。スタートアップ企業の技術顧問・アドバイザーやカメラマンもやってます。 今でも使える技術スタックだとPHP/Laravelぐらいです。COBOLも書けます。 ここ数年はEMやプロダクトマネジメント(PdM)と呼ばれる領域にウェイトを置くことが多いです。 ウェルミージョブとは 2025年7月に、 “カイゴジョブ” からリブランディングを行ったものが “ウェルミージョブ” です。 2025年3月期 決算及び会社説明資料より カイゴジョブはブランド名の通りもともとは介護中心の求人情報でしたが、介護・医療・障害福祉・保育の求人サイト「ウェルミージョブ」として、今後は職種横断のダイレクトリクルーティングプラットホームとして拡大・成長を実現するプロダクトになりました。 エス・エム・エス的に言うと、ウェルミージョブはキャリア事業という領域の中の1つですが、ナース専科転職やカイゴジョブエージェントはそれぞれ専任のキャリアパートナー(CP)が、就職・転職先を探している従事者へ働き方や条件に合う事業所を紹介したり、事業所からどういう人材が欲しいかの要望もヒアリングします。 それに対し、ウェルミージョブはCPがおらず、従事者は自分で事業所に応募する形、事業所も求人票を自分で記述して掲載するという形になっています。その分採用時にいただく料金もお安くなっている、という仕組みになっています。 課題抽出・仮説の設定 CPを介してヒアリングや紹介を行うサービスのことを、エス・エム・エスでは人材紹介と呼んでいます。 上述したとおりウェルミージョブはCPがいないぶん、基本的には従事者も事業所の双方に自律自走が求められます。 従事者目線で転職するとなると、いまの職場で働きつつ、どういう場所でどういう職場で働きたいのか、を自分で決めて見つけて、スケジュールを調整して面接をこなしていく必要があります。 事業所目線でいうと、小さな介護施設などは専任の採用担当もおらず、マネージャも現場での業務をこなしつつ採用もやらなきゃいけない状況であることが多いです。 当然ですが、従事者はウェルミージョブのサイトに来たときが一番モチベーション高く職場を探している状態です。事業所も求人票を掲載したいと思っているタイミングが一番人材がほしい状態になります。そこから実際に従事者が事業所に入職するまでの手間と時間をいかに減らすか、究極 “ゼロ” が理想、ということになります。 それらの要望を叶えるために、現在の状態を正しく把握する必要が出てきました。 企業は採用したいと思ったときから入職するまでに、なににどれぐらい手間と時間をかけているのか 求職者は就職・転職したいと思ったときから入職するまで、なににどれぐらい手間と時間をかけているのか そのなかから課題の大きさや重要さから、仮説検証すべき領域やフェーズのはなんなのか そのために成果物として作るべきものはなんなのか 現状分析から課題抽出した結果、それらを検証するためにスコープを絞ってMVP(Minimum Viable Product)を作る必要があるという判断をしました。 チームで議論しているときは「契約ってしないとだめなんだっけ?」「人が文章書かないといけないんだっけ?」「なにかモノを作らないといけないんだっけ?」といった、現状や常識に縛られない話も出てきました。もちろん契約や成果物が必要なのはわかってますが、角度を変えて見ることで新しいアプローチが見えたりと非常に有意義だったなと思います。 どのようにプロジェクトを進めるか このMVPでは、不確実性が高い状況で仮説検証を小さく素早く回す必要があったため、アジャイル的なアプローチを取ることにしました。 アジャイルで進めるということは、「いつまでに何ができるのか」を最初から明確に示せない、途中で方向転換する可能性がある、投資対効果の見通しが立ちにくい、といった特性があります。 組織にとっては、計画の不確実性を受け入れることになるため、慎重にならざるを得ない進め方です。 それでも、エス・エム・エスはこうした挑戦を許容してくれる環境です。 「なぜこのアプローチが必要なのか」「何を検証しようとしているのか」といった意義をしっかり説明すれば、会社として変化を受け入れ、任せてくれます。 不確実性の高い状況であっても、納得のいく説明さえできれば前に進める。そういった環境で、やりがいと責任を持ってプロジェクトを進められることを、日々感じています。 まとめ 今回は、ウェルミージョブで取り組んでいるMVP開発の事例を通じて、以下のような実践をご紹介しました。 従事者と事業所の入職までの手間と時間を減らすという課題に対し、現状分析から仮説を立てる 不確実性が高い領域では、スコープを絞ったMVPで検証サイクルを回す アジャイルアプローチを取ることで、計画の不確実性を受け入れながら前に進める こうした取り組みを進める上で大切なのは、「なぜこのアプローチが必要なのか」を説明し、組織の理解を得ることです。 エス・エム・エスでは、不確実性の高い挑戦であっても、その意義をしっかり伝えれば前に進める環境があります。役職や役割に関係なく議論でき、「サービスを通じて社会に貢献したい」という共通の価値観があるからこそ、こうした挑戦ができるのだと感じています。 さいごに エス・エム・エスに入社したのは、昔の同僚が声をかけてくれたのがきっかけでした。もちろん紹介は紹介でしかなくて、面接や面談でしっかりと情報交換をしていったのですが、会う人会う人全員が、立場や役割関係なく「社会のために我々は何をしていくべきか」を軸にお話をしていたのが非常に印象的でした。 弊社が以前から取り組んでいる、少子高齢、人口減少による生産年齢人口の減少という未来と、AIをはじめとした技術革新と、それを享受する社会や人類の情報リテラシーの変化の中で、 我々はなにをどう形にして世の中に価値を提供するのか を考え続けられる会社です。 そんな我々は一緒に働ける仲間を大・大・大募集しています!ここまで読んでくださったみなさんは、多少なりともエス・エム・エスという会社に興味を持っていただけてるはずです。まずは話だけでも聞いてみませんか?以下からご連絡お待ちしています! 最後まで読んでいただきありがとうございました。
こんにちは。2025年6月にエス・エム・エスに入社した柴山です。現在は介護/障害福祉事業者向け経営支援サービス「カイポケ」のリニューアルプロジェクトでQAエンジニアとして働いています。 プライベートでは1歳と4歳の子供を育てるワーキングマザーでもあります。今回は、多くのワーキングマザーが直面する「育児とキャリアの両立」という課題に私自身がどう向き合ってきたか。その「戦い方」と、新たな挑戦の場としてエス・エム・エスを選んだ理由についてお伝えします。 私自身の経験に基づく、かなり生々しい話も含まれますので、あらかじめご容赦いただけますと幸いです。 また、最近は男性育休の取得も増加傾向にあり(弊社でも取得報告は多く、非常に喜ばしいことです)、子育てとキャリアの両立は必ずしも女性に限った課題ではないと認識しています。それでもあえて今回は 女性のキャリアにフォーカス してお伝えできればと考えています。 育児とキャリアの両立に対する課題意識 子育て中の皆さん、仕事と家事と育児、どうですか?うまくいってますか?朝は子供のお世話や保育園の登園でへとへと、日中はなんとか仕事して、夜は寝かしつけや家事を終えてぐったり。残業する体力もないし、勉強会は大体アーカイブ配信を見るのみ……みたいな感じじゃないですか?少なくとも私はそうです。生活リズム、物事の優先度、仕事の向き合い方やキャリアの考え方。子供が生まれる前と後では全てが大きく変わりました。母親になって4年経ちますが、その変化には未だ困惑しています。 その中で、ここ数年私が悩んでいたのは、産休・育休による「キャリアの断絶」そして「マミートラック」でした。 キャリアの断絶 子供を妊娠・出産し、職場復帰するまでの期間は 最短でも7か月 *1 、長ければ2年 *2 に及びます。しかもこれは単純な休職期間の話。実際には妊娠初期の悪阻に始まり、食欲不振、頭痛、眠気、こむら返り、動悸、息切れなど様々な不調が伴います。そんな状態で、通常業務をこなして更にはスキルアップを目指すのは極めて困難です(少なくとも、私にはかなり厳しいものでした)。これは私の体感ですが、妊娠発覚直後からパフォーマンスは落ち始めます。ホルモンバランスの乱れもありますし、正直に言えば「流産が怖い」「禁忌事項が多すぎる」といったストレスも大きいのです。 そのため、職務経歴書上の経験年数と実務が一致しないといった事態も十分に起こります。私自身もエンジニア歴は10年ですが、2回の産育休を挟んでいるため、実務の期間は7〜8年ほどでしょう。同じ経験年数の人と比較したとき「若干スキルが劣るのでは?」と見られる可能性があります。それならば休職中にスキルアップを目指したり、復職後にバリバリ働いてギャップを取り戻そう、と考えるかもしれません。しかし、それもあまり現実的な解決策ではありません。なぜなら、前述の通り妊娠中は著しくパフォーマンスが下がるうえ、子を産んで復職すれば仕事と家庭の両立という正解のない課題が待っているからです。 マミートラック 子供を育てながら働く女性にとって、一度は聞いた単語かもしれません。出産した女性が本人の意欲とは関係なく、昇進から遠いキャリアコースに乗せられてしまう状態を指す言葉です。要するに、子供が生まれる → 短時間勤務や早退遅刻で仕事にかける時間が減る→スキルアップや重要な仕事に取り組めない → キャリアが停滞、あるいは下降する、という流れですね。 パートナーや親族を頼って時間を捻出すれば、このようなマミートラックは回避できるかもしれません。しかし近年共働き核家族化の影響で、自分たちだけで仕事も家庭もまわす必要があります。私もそうです。 特にIT業界は、技術の進化が非常に速いという特性があります。 1年、あるいは数か月で技術トレンドは移り変わり、休職前に使っていた技術がレガシーになることも珍しくありません。常に新しいOSSや設計・開発手法を学び続ける必要があり、近年はAIの発展によってそのスピードはさらに加速しています。 限られた時間の中で通常の業務と並行してスキルをアップデートし続けるのは容易ではありません。 このような要求の高い環境は、「キャリアの断絶」や「マミートラック」という課題をより一層深刻なものにします。 そして、「今の会社を離れることになった時、自分に市場価値はあるのだろうか」「このままITエンジニアを続けられるのだろうか」という、キャリアに対する強い不安に繋がっていくのです。 産休・育休後のキャリアチェンジという選択 この課題にどう向き合うべきか考えた末に、私が選択したのはキャリアチェンジでした。変化の速いIT業界でスキルが陳腐化するリスクと戦うよりも、全く新しい専門性を身につけることで仕事の幅を広げようと考えたのです。 私は現在QAエンジニアですが、それ以前はフロントエンドエンジニアとしてプロダクト開発に関わっていました。一人目の育休から復帰した際、休職による知識のギャップや開発環境の激しい変化に私は強い衝撃を受けました。仕事のスピードについていくだけで精一杯、「このまま最前線で戦い続けるのは難しい」と痛感したのです。そんな中、前職でQAエンジニアというポジションが新設されることになり、開発経験とテスト工程への理解があった私に声がかかりました。 正直、当時は未知の領域でしたが、これは 新たな専門性を築くチャンス だと感じました。特に、今後のテスト自動化などを推進する上では、これまでの 開発経験が大きな強みになる と確信し、キャリアチェンジを決意しました。 この選択によって私はマミートラックに陥ることなく、IT業界で生き抜く新たなスキルを手にしました。しかし、一人QAという環境では、どうしても自分の成長に限界を感じるようになります。ライフステージの変化に左右されず自身のキャリアを実現するためには、継続的にスキルアップできる環境に身を置くことが最善だと考えました。それが、今回の転職を決意した理由です。 とはいえ、転職活動を開始した矢先に妊娠が発覚したため、実際は出産後の育休中に転職活動を再開しました。この辺りの経緯はJaSST nanoでお話ししています。 エス・エム・エスに入社した決め手 子供がいる私にとって、転職活動では仕事内容だけでなく、働く環境も同じくらい重要視しました。いくつかの条件を軸に企業選びを進める中で、特にエス・エム・エスに入社を決めた3つのポイントをご紹介します。 働き方の柔軟性:リモート勤務を前提とした組織づくり 保育園に入園した途端に起こる「保育園の洗礼」、誰しも経験があると思います。保育園入園直後に子供が発熱や下痢症状を起こし、頻繁にお迎えの電話がかかってくる、療養のためしばらく保育園をお休みする、といった状況のことですね。こういった急な呼び出しにもすぐ対応できる、子供を自宅看護しながら最低限仕事ができる、という理由からリモート勤務を希望しました。また将来的な地方移住も視野に入れ、長く働ける環境というのも1つのポイントでした。そのため、地方在住者が所属しているかも条件に加えました。 私が所属するプロダクト推進本部では、リモートワークを基本としながらも、出社するか在宅するかを選択できる体制が整っています。入社初日のオリエンテーションや総会などで出社が必要な場合も、事前に家庭内で調整して参加しています。 組織内には関東圏外の在住者も多く(私の知る限り、北は北海道から南は九州まで)、チーム内にも京都からリモートで働くメンバーがいます。場所が離れていてもチームのコミュニケーションに不都合を感じないのは、オンラインで円滑に連携できる組織づくりがされているからだと感じています。こうした柔軟な環境であれば、将来的に移住といったライフステージの変化にも対応できそうだと感じました。 専門性を高める環境:QAチームの存在 前職においてはQAエンジニアが一人という関係上、QA同士で業務相談ができない、という課題がありました。勉強会の内容をシェアしたり、品質に対する議論をしたり「他のQAチームはどのように工夫しているのだろう?」といった情報交換ができなかったのです。そのため、QAチームが存在すること、具体的には3名以上QAが在籍していて、横断的活動やコミュニケーションの場があることを条件に転職活動をしました。 エス・エム・エスでは、複数のQAエンジニアが所属しており、各プロダクトの品質向上活動を行なっています。同じプロダクトの別チームの様子も聞けるし、別プロダクトのQAエンジニアにお話を伺う機会もあるので、情報共有や交換がとても活発です。 また、組織としても勉強会やカンファレンスの参加を推奨しています。先日行われたJaSST Niigataも、メンバー間で活発な意見交換が行われていました。私は現地参加でしたが、他の方々はオンライン参加でした。いつかチームメンバーと現地参加できることを楽しみにしています。 相互理解と文化:面接で感じたフィット感 転職活動終盤、ありがたいことに2社内定を頂きました。私が希望する上記の条件はどちらも満たしていたので、どう決めようかと相当悩んだのを覚えています。その時に最終的な決め手となったのが、エス・エム・エスのオファー面談における誠実さと熱量、フィット感でした。 エス・エム・エスのオファー面談で印象に残ったのは、自分の強みだけではなく弱みまで伝えられ、それが自分の理解と一致していた(=私に対する解像度が高かった)こと。そして、入社後に活かすべきスキルと期待される活動が、かなり具体的かつ明確に示されたことでした。 そのおかげで入社後のイメージをより強く持つことができ、入社を決めました。 入社後に感じた、子育てと両立しやすい環境 ここからは、実際に入社して4か月で感じた「子育てと両立しやすい環境」についてお伝えします。 カルチャーと周囲の理解 まず、入社して特に重要だと感じたのは、会社のカルチャーです。 私が所属する組織には子育て世代が多いということもありますが、それに関わらず、お互いのプライベートを尊重し、仕事上でサポートし合う文化が根付いています。家族や自身の体調不良に関しても、仕事の調整が非常にやりやすく助かっています。 また、子供の体調不良などで自宅保育しながら勤務せざるを得ない状況もあります。そういった場合にもチームメンバーは業務調整など快くサポートしてくれます。実際私も転職したての頃は何度か子供を保育しながら仕事をしていましたが、ミーティングに子供が映り込んでしまうようなアクシデントも、温かく受け入れてもらえました。 柔軟な勤務を支える制度 私が所属するプロダクト推進本部では、コアタイム(12:00〜16:00)ありのフレックスタイム制度を導入しています。このコアタイムに勤務していれば、始業・終業時間は個人の裁量で柔軟に調整することが可能です。 そのため、朝の時間を活用して8時から業務を始めるメンバーもいれば、午前中に用事を済ませてからコアタイムが始まる12時に合わせて勤務を開始するメンバーもいます(もちろん、月当たりの定められた労働時間を満たすことが前提です)。 私自身もこの制度を活用し、普段は子供を保育園に送った後の9時頃から、お迎えの時間に合わせて18時頃まで勤務しています。もちろん、子供の通院などで日中の勤務が難しい日もあります。そういった場合は、コアタイム以外の時間を調整することで対応しています。 また、時間単位の休暇制度もあり、1時間単位で休暇を取得できます。子供の予防接種や役所での手続きなど、短時間の離席が必要な際にこの制度を活用することで、業務への影響を最小限に抑えつつ家庭の用事にも対応でき非常に助かっています。 これらの制度やカルチャーに助けられながら、仕事と子育てに奮闘している状況です。 仕事と子育てに追われる一日のスケジュール ここでは私のとある平日のスケジュールをご紹介します。出社や子供の通院などがある日は変動しますが、普段は概ねこのような流れで一日が過ぎていきます。 我が家は夫婦共にリモートワーク(旦那はたまに出社)かつ保育園が近所なので、フルタイム勤務でギリギリ家庭を回している状態です。これが1つでも欠けていたら絶対に無理だろうな〜と日々思っています。 06:00 起床・朝の準備 08:30 保育園登園 & 業務開始 12:00 昼食 17:50 業務終了・お迎え 18:30 帰宅・夕食 19:00 お風呂 21:00 寝かしつけ・残りの家事 子供たちがいない間はほぼ勤務時間なので、家事は昼休みや隙間時間にねじ込んでこなしています。やはり家事に手間をかけられないので、食器洗浄機やロボット掃除機、ドラム式洗濯機は必須です……。 特にご飯を作る時間(食材調達から食材管理、献立、調理、後片付け含む)が圧倒的にないので、我が家では つくりおき.jp *3 を活用しています。とてもおいしくて経済的で時短にもなります。でもママの作った料理じゃなくてごめんねっていう謎の罪悪感に駆られるんですよね。これが地味にメンタルに来るんだよなあ〜。とはいえフルタイム勤務しながら夕食を作るのは(私には)絶対に無理です。時間のない中作ったご飯を残されても悲しいしね。 おわりに:ライフステージの変化とキャリア形成 ここまで、産育休と女性のキャリアや仕事と子育ての両立について語ってきました。決して偉そうに語れる立場ではなく、そんなに上手く立ち回れているわけでもない、というのが正直なところです。「子育てを言い訳に仕事を諦めたくない」という気持ちと、「とはいえ仕事に全力投球して家庭を顧みないのは、家族として健全ではないよね」という現実との間で今も毎日のように葛藤しています。 子供がまだ未就学児で保育園に助けられている部分もあるけど、小学生に上がったらどうなるんだろう、学童に行ってもらう?夏休みはどう乗り切ろう?といった先の心配で頭がいっぱいです。まあでも正直なるようにしかならないんだろうな、と最近は割り切るようになりました。子供や家庭に何か大きな変化があった時、会社員を続ける選択ができるよう、少しずつでもキャリアを積み上げていきたいです。 現在はQAエンジニアとして、主にPlaywright(コードベースのE2Eテストツール)を用いたテスト自動化の推進に取り組んでいます。この活動はこれまでの開発経験を大いに活かせる領域です。他にも開発者視点でテストの課題や改善点を見つけ出し、それを解決していくプロセスを通じて、QAエンジニアとしての専門性を高めていけたらと考えています。 私自身、特別要領が良いわけでも体力があるわけでもありません。たぶんどこにでもいる普通のワーキングマザーです。だからこそ、この記事が同じ境遇で働く方々の支えになれたらと願っています。 こうしたライフステージの変化はキャリアを諦める理由ではなく、働き方や自分自身を見つめ直す最高の機会なのかもしれませんね! *1 : 10月ごろに出産し、0歳児クラスに生後5か月で預けるパターン。産前休業が出産予定日の1か月前なので9月に休職、4月に保育園入園と同時に復職する想定。 *2 : 0歳児クラスで入園できなかったパターン。2歳の誕生日前まで育休の延長が可能。 *3 : 数日分の食事を宅配で届けてくれるサービス。おかずのみが冷蔵で届くので、ご飯と汁物さえ用意すれば栄養バランスの整った食卓が実現できて助かっています。おいしいし。忙しい家庭におすすめ!
こんにちは。介護・医療・障害福祉・保育の求人サイト、ウェルミージョブのQAを担当している林です。 ウェルミージョブは、2025年7月にカイゴジョブからリブランディングしてサービス提供を開始しました。 私は先日Kaigi on Rails 2025に参加してきました。私はQAエンジニアでProduction Readyなコードは書けませんが、開発系のカンファレンスに興味があり、今回生まれて初めて参加しました。会場ではセッションを聴講したり自社ブースでの対応をおこないまして、感想としては、控えめに言って すごくすごくよかった です!このブログでは、コードが書けないQAエンジニアの私が、開発系カンファレンスで何を感じ、開発とQAの意外な「共通点」をどう見つけたのか?具体的な学びとともにお伝えします。 自己紹介 QA歴は10数年で、2021年5月から現ウェルミージョブ(当時のカイゴジョブ)の開発チームへ、専属QAの一人目としてJOINしました。当時は人生初の一人目QA・育休明け・初のリモートワーク・コロナ禍における様々な影響などにより多くの困難がありましたが、アジャイルな開発チームの中で、持ち前のコミュニケーション能力と「握ったボールは自分でやり切るor誰かに渡す」の精神で乗り切ってきました。  私の開発系技術スペックはこんなかんじです。 大学はバリバリの文系で、開発系技術とは無縁 新入社員時代、必須受講のC言語研修にて、ポインタで挫折して泣いた(ほんとうに) QAエンジニアとして業務をしながら、2016年に基本情報技術者(FE)に合格。開発系の資格はこれのみ所有 過去には「仕様書がない・触れるシステムもまだない」案件で、ER図からがんばってテスト設計をやり遂げた経験あり SQLやAPIについて積極的には実行しないが、幸いにも年1回程度は触ったり勉強したりする機会に恵まれている アジャイルな開発チームにて日々、開発メンバー同士の会話を横で聞いている。そのため、テーブル・データ・モデル・処理などが大まかにイメージできている なぜ「Kaigi on Rails 2025」へ参加したのか? Kaigi on Railsは、「初学者から上級者までが楽しめるWeb系の技術カンファレンス」をコアコンセプトとした技術的な学びの場であり、多様な人々が交流できるイベントです。 kaigionrails.org エス・エム・エスはKaigi on Rails 2025へGoldスポンサーとして協賛し、スポンサーブースにてウェルミージョブのソースコードを公開しました。 このKaigi on Rails 2025へなぜQAの私が参加したかというと、2つの目的があったからです。 @moro さんの基調講演を聴くため :ウェルミージョブの開発をリードする@moroさんがKeynote Speakerとして登壇して基調講演を務める運びとなり、私もそれを現地で聞きたいと思いました。普段からチーム内に共有されている@moroさんの考えが、多くのエンジニアに響くのを肌で感じたいと思いました。@moroさんが楽しそうな様子で準備しているのを身近で見ていたこともあり、私を含め多くのチームメンバーがワクワクしていました。さらに、開発チームのメンバーから「林さんも一緒に現地で楽しもう」とお誘いがあったことも参加の後押しになりました。 開発エンジニアの考えや課題感を知るため : セッションの視聴やブースでの交流によって開発エンジニアのことが知れると、それが開発とQAの相互理解を深める土台となって、より強い連携を築けるのではという期待がありました。   参加してわかった!セッションからの学び 特に印象に残った2つのセッションについてご紹介します。  1. 基調講演:dynamic! speakerdeck.com 要約 なぜ動的/dynamicにしたいのか :この発表では「動的/dynamic」とは「継続して変化し続けること」を指します。不確実性の高いプロダクト開発において「初めから正解を選ぶ」のは難しいため、一度に正解を目指すのではなく、良い方向を目指して少しずつ変わることを大事にしたいです。そしてそれは、楽しいことです。 フィードバックから得られる価値 :「最もシンプルで、うまくいく」ものは何かを見極めて、作ってみて動かして、フィードバックをもとに変化させ続けます。動かすことで、開発者だけでなくデザイナーやQAエンジニアなどがそれぞれの職能を発揮できます。企画者も、事業活用の計画を判断できたり見直せたり、ドキュメントではなく動くソフトウェアをベースにコミュニケーションを円滑におこなえます。 あらゆるものを動的に習熟していく :見極めたり、一度作ったものを変えるのは簡単ではありません。そのため、コード・プロダクト・プロセス・チーム・自分自身も含めてあらゆるものを少しずつ動的に習熟していきます(※1)。変わることを楽しみましょう! (※1) 所感 現地で聞けて良かった! :会場では多くの賛同のリアクションや拍手が起こり「良いプロダクトを作りたい」と願う人々の心が一つになったような感動を覚えました。講演の内容は、ウェルミージョブ開発の中で@moroさんが日々体現されていることをそのまま資料に落としたようなものでした。改めて、魅力あるプラクティスに日々トライできることへの喜びを感じました。 変化に対応するQAの課題感と、それを解決する可能性 :QAエンジニアとして日々変化についていくのは容易でなく、高頻度に発生する追加のテスト設計・実施を軽やかにおこなうための工夫が必要です。ここで私は「忍者式テスト」を思い出しました。( 忍者式テストの講演資料はこちら )忍者式テストとは深谷美和氏・関将俊氏によって提唱されるプラクティスで、反復開発の中で「増分だけでなく、プロダクト全体を都度テストする」というものです。忍者式テストでは、開発者もテストを実行してプロダクトから学び、修正や改善を積極的にできるようになるメリットがあるそうです。私は、忍者式テストへの挑戦も含めて、今後さらに軽やかに変化対応できるようトライしていきたいです。 不安を軽減するコミュニケーションの重要性 :動的に開発が進むことにより、例えば企画者は「最終決定がいつ頃になるのか見通せない」と不安を覚えるかもしれません。そんな場面では、ステークホルダーが必要とするものが何かを知り、より相互にコミュニケーションをとり、必要なドキュメントはシンプルに残すなどして困り事や不安を取り去ることが大事になりそうです。 変わるのは、楽しいこと。変えられるのは、ハッピーなこと! :課題もありますが、不確実性の高いプロダクト開発において動的に物事を進めることのメリットは多大です。私もQAエンジニアとしてあらゆる変化を楽しみながら、よりよいプロダクト開発に尽力したいです!    2. Railsによる人工的「設計」入門 speakerdeck.com 要約 設計を体得する・教えることの課題感 :「設計」を体得したり教えるのは難しいことです。一方で、今後はAIが普及して設計の機会が減り「場数を踏んで体得する・させる」のが難しくなりそうです。さらに、AIを使いこなすためには設計できる能力が重要です。そのため、設計を教える人が「設計を教えられる」ようになっている必要があります。  手順から逆算して考えるアプローチ :設計ができない人は「コードを書くとシステムができる」と考えがちですが、設計とはコードとは違って、抽象的なレベルで考える活動です。「コードを意識しないで設計する」ように導くのに「システムができる手順から逆算して考える(※2)」というアプローチが有効でした。まず「完成したシステム」を思い浮かべ、もっとも実現したい本質的な事柄を「ゴール」と定めて、その実現に必要なことを段階的に考えるというステップで、抽象的なレベルで設計していきます。  (※2) 「名前付け」の重要性 :抽象化する作業において「名前を付ける」ことは重要です。長い概念を適当に省略してしまうと、本質から外れたところにミスリードされてしまいます。名前付けに苦手感がある人も、勇気を出して、本質を表す名前を自分の裁量でつけましょう。 所感 「抽象化する能力」の課題感はQAも同様 :QAにとっても抽象化する能力は重要です。例えばテスト分析という過程で「何をテストするか」を定義する際、抽象化が苦手な人はテストケースなどの細かい粒度で考えてしまってテスト全体を捉えられません。さらに、体得する過程における課題感も開発と同様、AIの普及で体得する機会が減りそうです。そのため、QAにとっても「人工的に抽象化を体得させるメソッド」はとても役に立ちそうです。 「逆算して全体像を考える手法」はQAにも適用可能 :先述した「システムができる手順から逆算して考える(※2)」の文脈で、私は、西康晴氏によって提唱されたVSTeP(「何をテストすべきか」という観点を図で整理し、抜け漏れなく効率的にテストを設計するための手法)( VSTePの講演資料はこちら )を思い出しました。VSTePでは、「テスト要求分析」「テストアーキテクチャ設計(コンテナ設計・フレーム設計)」などの工程を経てテスト全体をアーキテクトします。このうちの「テスト要求分析」の際にテスト観点(テストすべき要素)を整理するにあたり、逆算の手法を適用してみると、以下のステップで進められそうです。 「完成したシステム全体」を思い浮かべる 中核的な「実現したいこと」にフォーカスする 「実現したいこと」に対して「ユーザーに使ってもらって大丈夫、となれるには何の確認が必要か?」を順々に考えていって、全部考えた状態にする QAも「勇気を出して名前付けをしよう」 :名前付けの重要性や課題感もQAに共通するところだと感じます。名前付けがしっくりこないときは「大事なものの見極め」がうまくいっていないサインですし、間違っていればチームメンバーがそれを教えてくれ、より正しく抽象化ができるようになります。「勇気を出して、本質を表す名前を、自分の裁量でつけよう」というメッセージを、多くのQAエンジニアにも届けたいです。  開発・QAが類似課題を共有して解決できる可能性 :開発・QAの類似課題について、開発・QA両者が情報や知恵を出し合えると、よりよい解決の方向性が見出せると思います。さらに、VSTePの講演資料の「テスト開発プロセスの基本的考え方(※3)」において「テストケースを開発成果物と捉え、ソフトウェア開発プロセスとソフトウェアテスト開発プロセスを対応させよう」とあるように、開発とQAは様々なプロセスでリンクしています。設計のタイミングだけでなく、多くのプロセスにおける開発・QAの連携が期待できそうです。 (※3)出典: VSTePによるソフトウェアテストの開発 ブース対応で感じたQAの可能性 今回はスポンサーブースに立ち、来訪者への対応をおこなう機会もありました。具体的な実装に関する受け答えができないので不安でしたが、いざやってみると、QAならではの強みを発揮できたと感じています。 プロダクトの「体験」を提供 :テスト用端末を使って来場者に実際にプロダクトを触ってもらうことで、コードだけでは伝わらない魅力を伝えることができました。 多様な情報提供 :テックブログやウェルミーマガジンなど、プロダクト以外の情報も提供することで、来場者との会話を広げることができました。 QAの魅力を発信 :開発チームの中でQAがアジャイルに活躍していることを開発メンバーからも話してもらえて、QAの存在や魅力がより伝わったかと思います。また、ウェルミージョブの開発チームが「異なる業種間のコミュニケーションが良好なチーム」であるという魅力が発信できた点も有意義でした。さらに、来訪者の方にはQAの話に興味を示してくれる方もおり、QAからの情報発信の場として開発系カンファレンスは有効な場所となる可能性を感じました。  たくさんの人との出会い・関わり 2日間のセッション聴講やスポンサーブース対応を通じて多くの方々と関わることができました。開発業務が主担当ではない私の参加を歓迎していただき、また、QAという領域にも興味を持っていただくことができました。いずれの方も、カンファレンスへの参加や交流を心から楽しんでいる姿がとても印象的でした。 運営メンバー ブース対応を共におこなった開発チームメンバー ブースの来訪者 他社ブースの方、本屋さんやコーヒーなどを提供してくださった方 現在一緒に業務している方、過去に業務でご一緒した方 開発チームメンバーの方の紹介があって出会えた方… また、私が身に着けているエス・エム・エスのロゴを見た多くの方から「○○さんの会社の」と声をかけていただきました。これらの出会いは、エス・エム・エスで活躍する人のつながりによって生まれた貴重なもので、私もそのつながりを大事に紡いでいきたいと思います。  一方で、普段とは違って多くの人と関わる場面のため、意識して気を付けようと思ったことがあります。それは「人を尊重すること」です。 安心して気持ちよく過ごせるために :アンチハラスメントポリシーはもちろん遵守します。さらに、そこからもう一歩踏み込んで「お互いが気持ちよく安心して過ごせるためのマナー」も大事にしたいと思いました。 楽しいからこそ要注意! :楽しさから気が緩んでしまったり、一体感や高揚感から「このくらいの言動は大丈夫だろう」と判断を誤ってしまうかもしれません。「普段から私は気を付けているから大丈夫」と過信せず、一呼吸おいて判断することが大事だと思いました。 尊重する相手は「すべての人」 :尊重する相手は、お客様にあたる立場の方・運営メンバー・自社のチームメンバー・友人知人・会場や廊下などでたまたま物理的に距離が近づいた人と多岐に渡ります。そして(私の個人的な感覚かもしれませんが)「自分自身」もその対象に入れると、自然に「すべての人を尊重する」が実行できるような気がします。そのため、自分自身も大事にしたいなと思いました。 まとめ 今回の開発系カンファレンス参加を通じて、開発エンジニアとQAエンジニアは「 よりよいプロダクトを作りたい 」という同じ気持ちを強く持っていることを再確認しました。 「 dynamicにシンプルに 」プロダクト開発を進めることは容易ではありませんが、関わる人と相互理解のもとコミュニケーションをとって 楽しんで 実現していけると確信しています。 QAが開発系のカンファレンスに参加する意義は、自身のスキルアップだけでなく、 QAの存在や意義を広く知ってもらうこと や 開発・QAの相互理解からの連携強化 にも繋がります。開発エンジニアのみなさんにも、ぜひ品質保証に関するカンファレンスに参加していただけたら嬉しいです! 「コードが書けないQAが開発系カンファレンスに参加する」、2回目のチャレンジを目指して現在鋭意調整中です!  お知らせ スポンサーブースで大好評だった ウェルミージョブのソースコード公開 は、カジュアル面談にておこなうことも可能です。「カンファレンスへの参加が叶わなかった」「時間がなくてブースに行けなかった」「ブースでコードを見てみたが、もっと見たい」という方がいらっしゃいましたら、ぜひ、カジュアル面談しましょう! @moroをはじめとしたウェルミージョブの開発メンバーが(ご要望あればQAメンバーも)、みなさんとお話できるのを楽しみにしています。  
はじめに こんにちは。プロダクト開発部の髙木です。先日、弊社のブログでテックブログの入稿システムについて紹介しました。このシステムは、ブログ記事の作成から投稿まで、これまで手作業で行っていた工程を大幅に自動化し、記事執筆に集中できる環境を提供するものです。 tech.bm-sms.co.jp このシステムを運用している中で、サムネイル画像生成機能において、一部の文字が太字にならないという問題が発覚しました。調査・修正を行う過程で、技術的な問題を解決するだけでなく、チーム開発において非常に重要な「どうしてこうしたんだろう?」を考えるきっかけを得られました。 問題の発見と原因の特定 サムネイルの文字が太字にならない 今回問題となったのは「絆」という漢字でした。通常、サムネイル作成システムによって生成される画像では、すべての文字が統一された太字フォントで表示されるはずです。しかし、ある記事のサムネイルを確認したところ、「絆」という文字だけが細字で表示され、他の文字と視覚的に異なる状態になっていました。 この現象を詳しく調査したところ、リポジトリに内包していたフォントファイルにその文字が含まれていないことが判明しました。システムは存在しない文字を代替フォントで表示していたため、視覚的な違いが生じていました。技術的な挙動の原因は特定できましたが、そもそもなぜそのような問題が起きる状態になっていたのか、その背景や経緯については不明でした。 最初のアプローチ:Google Fontからのダウンロード 問題の根本的な解決を図るため、まずはGoogle FontsからNoto Sans JPのフォントファイルをダウンロードし、既存のフォントファイルと置き換えることにしました。この新しいフォントファイルを使用してサムネイル生成をテストしたところ、期待通り「絆」という文字も正しく太字で表示されるようになりました。 問題が解決したと安心して、この修正をコミットしてリモートリポジトリにプッシュしようとしたところ、予想外のエラーが発生しました。これまでそのような大きなファイルを扱った経験がなかったため、Gitでは約1MBを超えるファイルをプッシュしようとするとサイズ制限によってエラーが出ることを、このときに初めて知りました。 サブセット化という解決策 バッファサイズ変更よりも良い方法 最初は、Gitの設定でバッファサイズを上げて大きなファイルをプッシュできるようにすることを検討しました。しかし、調べている過程で、フォントファイルのサブセット化という、より根本的で効率的な解決手法があることを知りました。 サブセット化とは、フォントファイルから実際に使用しない文字を排除して、必要最小限の文字セットのみを含むフォントファイルを作成する技術です。今回のブログのサムネイル生成という用途を考えると、日本語のすべての文字を含む必要はありません。そのため、ファイルサイズを大幅に削減できるサブセット化の方針の方が、長期的に見てもメンテナンス性やパフォーマンスの観点から適切だと判断しました。 「絆」が含まれなかった理由 今回使用していたフォントファイルに「絆」が含まれなかった理由を考えてみました。結構身近に感じていた漢字でしたが、この漢字が常用漢字に含まれないことがわかりました。たしかに子ども頃に習った記憶はない気がする…。 今後も常用漢字以外の漢字をタイトルに使用する可能性があります。そのため、ある程度使用される可能性のあるフォントはサブセット化する際に含めておく方が安全であること考えました。 常用漢字以外の文字の選定 使用される傾向のある常用漢字以外の漢字は、文化庁の資料から抽出しました。 常用漢字表の字体・字形に関する指針(報告)について(報告) | 文化庁 こういったPDFから抽出するコードをさっと作ってくれるのは、LLMの良いところだなと改めて思いました。 結果と成果 それらの文字を含めたフォントファイルを作成したところ、1MB未満となりコミット、プッシュすることができました。 先駆者の行動をリスペクトする 「なぜそうしたのか」を理解する 記事のタイトルに戻りますが、おそらくこの問題は、このシステムを担当した方も全く同じことを考えたのだと思います。フォントファイルを入れてみたら1MBを超えていて、ファイルサイズを減らすために常用漢字のみを入れたフォントファイルを作成したのだと思います。 想像力と知識の不足を認める 日常的に「どうしてそうしなかったんだろう」と思うことは多いですが、自分が同じ立場に立つと「だからこうしたんだな」となることが多いです。それは自分の想像力が足りていないこともありますが、知識が足りていなくてそのような結論になってしまうことが多いと感じています。 先駆者の行動はリスペクトを持って分析し、その上で「こうした方が良さそう」にもっていくことは、同じチームとして活動していく仲間として大切な考え方です。技術的な問題を解決することは重要ですが、その過程で過去の意思決定を否定するのではなく、理解し、その上で改善を提案することが建設的だと考えています。 おわりに 今回のフォントファイルのサブセット化を通じて、技術的な問題解決だけでなく、チーム開発において重要な視点について改めて見直す良いきっかけになりました。「絆」という漢字にぴったりのテーマだったということもあり書いてみました。 自分の知識が深まれば深まるほど、自分の考えが適切であると考えることが増えていくと思います(その考えが間違っていることもたくさんありますが…)。そのような状態でも、先駆者の行動の理由を理解し、リスペクトを持って改善を進めることは、自分の知識も深めつつ良いチームになっていくうえで必要なことだと改めて思いました。自分だけの話ではなく、一緒に働いている人とやりやすく仕事をしていくうえで大切にしていこうと思います。
はじめに こんにちは!カイポケのリニューアルプロジェクトを担当しているエンジニアのNobです。 普段はWebのフロントエンドが中心ですが、最近はモブプロをとおしてバックエンドのタスクにもチャレンジさせてもらっています。 プライベートでは2歳になったばかりの息子の子育てに奮闘中です。最近は話せる言葉が増えて少し会話が成り立つようになってきたり、遠くへの外出でも泣かなくなってきました。子育ては大変ですが、それ以上に子供からたくさんの笑顔と幸福感をもらっています。 さて、今回はESLintに追加されたMultithread Lintingについて、私が携わっているプロジェクトのCIへの導入を検討したので共有します! Multithread Linting 機能の概要 ESLint v9.34.0で追加されたこの機能は、その名のとおりESLintによるチェック処理を並行して実行することによって高速化するものです。リリースとともに 公開された Blog によると、1.3倍から3倍ほど高速化した例があるようです。大規模なコードベースで開発している我々としても高速化が期待できそうなので試してみることにしました。 concurrency オプションの設定値 concurrencyに指定可能な値は以下のいずれかです。 正の整数: 最大のスレッド数。任意の数を指定。 auto : CPUのコア数と対象ファイル数に基づいてESLintに並列数を決定させる。 off : Multithread Linting機能を無効にする。デフォルト。 auto がうまく機能しそうであれば、実行環境に合わせて値の調整をしなくて済むので手間が省けそうです。なので、まずは auto から試してみることにしましょう。 初回ベンチマーク: off vs auto 現在の私の開発端末のスペックは以下です。 MacBook Pro: 14インチ、 Nov 2024 CPU: Apple M4 Max メモリ: 64GB この端末で現在私が開発に携わっているプロジェクトを対象に、どのくらい処理速度に変化があるのか見てみましょう。まずはESLintの処理速度の変化を検証したいので、 ESLintのキャッシュを利用しない状態で比較してみます。 ベンチマークには hyperfine というコマンドラインベンチマークツールを使用します。 hyperfine --warmup 1 --runs 3 -L concurrency off,auto " pnpm exec eslint --concurrency {concurrency} './**/*.{ts,tsx,graphql}' " Benchmark 1: pnpm exec eslint --concurrency off ' ./**/*.{ts,tsx,graphql} ' Time ( mean ± σ ) : 62 . 363 s ± 0 . 257 s [ User: 74 . 000 s, System: 10 . 615 s ] Range ( min … max ) : 62 . 110 s … 62 . 624 s 3 runs Benchmark 2: pnpm exec eslint --concurrency auto ' ./**/*.{ts,tsx,graphql} ' Time ( mean ± σ ) : 76 . 222 s ± 1 . 714 s [ User: 262 . 973 s, System: 138 . 288 s ] Range ( min … max ) : 74 . 245 s … 77 . 297 s 3 runs Summary pnpm exec eslint --concurrency off ' ./**/*.{ts,tsx,graphql} ' ran 1 . 22 ± 0 . 03 times faster than pnpm exec eslint --concurrency auto ' ./**/*.{ts,tsx,graphql} ' 試した結果、期待とは違って --concurrency auto を指定した場合の方が1.22倍時間がかかるようになってしまいました。なぜこのような結果になってしまうのか少し調べてみましょう。 auto モードの並列数決定ロジック まずは --concurrency auto を指定した場合、並列数がどのような処理で決定されるのか調べてみます。 concurrency というキーワードでgrepしてESLintのコードを眺めてみると、どうやら このあたりの処理 で判断しているようです。 case "auto" : { workerCount = Math . min ( availableParallelism() >> 1 , Math . ceil (fileCount / AUTO_FILES_PER_WORKER), ); break ; 周辺コードも含めて少し噛み砕いて見ていくと availableParallelism() >> 1 この availableParallelism() はNode.jsの標準ライブラリの os.availableParallelism() であり、その実体は libuv の uv_available_parallelism() 。OSやCPUによる細かな違いはあるものの、シンプルに言えばプロセスが利用可能なCPUのコア数を返す。 availableParallelism() の結果を1ビット右にシフト(2で割って小数を切り捨て)した値となる。 Math.ceil(fileCount / AUTO_FILES_PER_WORKER) fileCount は対象ファイル数。 AUTO_FILES_PER_WORKER は 35 という定数 。 この値はヒューリスティックな値であり、将来的により適切な値や算出処理に改善される可能性がある。 のように読みとることができます。最終的にはそれぞれの値のより小さい方が並列数として使用されることになります。 これを思い切って単純にすると Math.min(CPU のコア数の半数, ファイル数 / 35) となります。 ではここで ファイル数 / 35 が実際にどのくらいの値になるのか考えてみましょう。 100 / 35 => 2.8… 300 / 35 => 8.5… 500 / 35 => 14.2… のようになり、この値の比較対象がCPUのコア数の半数であることを考慮すると、対象ファイルが500以上あるような比較的大規模なプロジェクトではCPUのコア数の半数が並列数になると考えることができます。 検証端末での並列数計算結果 前述のとおり、並列数の算出にはCPUのコア数と対象のファイル数が関係してくるのでした。今回検証に使っているプロジェクトには4,000ファイル以上が存在しています。対象ファイル数が十分に多いため、並列数はCPUのコア数で決まると考えることができそうです。 検証に使っている開発端末のCPUはApple M4 Maxであり、この環境で availableParallelism() が返す値は16です。 node -p " require('node:os').availableParallelism() " 16 この値を2で割った値、つまり8が並列数として利用されることになります。実際に並列数として使用された値はESLintの実行時に --debug オプションを指定することで出力されるログからも確認することができます。 eslint:eslint Linting using 8 worker thread ( s ) . ここでApple M4 Maxのコアの内訳を見てみましょう。 12個がPerformanceコアで4個がEfficiencyコアです。 Performanceコアは高いクロック周波数で動作するCPU集約的なタスクが向いているコアで、 Efficiencyコアは低消費電力で動作する電力消費効率を重視したコアです。 一方Node.jsが利用しているlibuvの uv_available_parallelism() ではこれらのコアの違いを知ることはできません。 16個のうちの4個が他のコアよりも性能が低いことを考慮すると、 8という並列数は実際のスペックよりも高い値なのかもしれない、という仮説をたてることができます。 最適な並列数の探索 それでは実際に8以下の並列数で改めて検証してみましょう。 hyperfine --runs 1 -L concurrency off, 2 , 3 , 4 , 5 , 6 , 7 ,auto " pnpm exec eslint --concurrency {concurrency} './**/*.{ts,tsx,graphql}' " Benchmark 1: pnpm exec eslint --concurrency off ' ./**/*.{ts,tsx,graphql} ' Time ( abs ≡ ) : 64 . 260 s [ User: 75 . 702 s, System: 11 . 435 s ] Benchmark 2: pnpm exec eslint --concurrency 2 ' ./**/*.{ts,tsx,graphql} ' Time ( abs ≡ ) : 51 . 809 s [ User: 108 . 378 s, System: 22 . 637 s ] Benchmark 3: pnpm exec eslint --concurrency 3 ' ./**/*.{ts,tsx,graphql} ' Time ( abs ≡ ) : 48 . 950 s [ User: 135 . 421 s, System: 35 . 065 s ] Benchmark 4: pnpm exec eslint --concurrency 4 ' ./**/*.{ts,tsx,graphql} ' Time ( abs ≡ ) : 49 . 328 s [ User: 163 . 220 s, System: 50 . 156 s ] Benchmark 5: pnpm exec eslint --concurrency 5 ' ./**/*.{ts,tsx,graphql} ' Time ( abs ≡ ) : 52 . 281 s [ User: 187 . 664 s, System: 67 . 241 s ] Benchmark 6: pnpm exec eslint --concurrency 6 ' ./**/*.{ts,tsx,graphql} ' Time ( abs ≡ ) : 59 . 303 s [ User: 216 . 758 s, System: 91 . 124 s ] Benchmark 7: pnpm exec eslint --concurrency 7 ' ./**/*.{ts,tsx,graphql} ' Time ( abs ≡ ) : 67 . 345 s [ User: 236 . 109 s, System: 113 . 020 s ] Benchmark 8: pnpm exec eslint --concurrency auto ' ./**/*.{ts,tsx,graphql} ' Time ( abs ≡ ) : 72 . 838 s [ User: 263 . 605 s, System: 133 . 785 s ] Summary pnpm exec eslint --concurrency 3 ' ./**/*.{ts,tsx,graphql} ' ran 1 . 01 times faster than pnpm exec eslint --concurrency 4 ' ./**/*.{ts,tsx,graphql} ' 1 . 06 times faster than pnpm exec eslint --concurrency 2 ' ./**/*.{ts,tsx,graphql} ' 1 . 07 times faster than pnpm exec eslint --concurrency 5 ' ./**/*.{ts,tsx,graphql} ' 1 . 21 times faster than pnpm exec eslint --concurrency 6 ' ./**/*.{ts,tsx,graphql} ' 1 . 31 times faster than pnpm exec eslint --concurrency off ' ./**/*.{ts,tsx,graphql} ' 1 . 38 times faster than pnpm exec eslint --concurrency 7 ' ./**/*.{ts,tsx,graphql} ' 1 . 49 times faster than pnpm exec eslint --concurrency auto ' ./**/*.{ts,tsx,graphql} ' どうやら私の端末では明示的に --concurrency 3 を指定することで off の場合よりも1.31倍、 auto の場合よりも1.49倍高速なようです。 concurrency auto を指定すると遅くなってしまうものの、適切な並列数を明示的に指定することで良いパフォーマンスを得ることができそうです。 キャッシュ有効時の性能比較 これまではESLintのキャッシュが無効な状態で検証をしてきました。次はESLintのキャッシュが有効な状態はどのような結果になるか試してみます。 hyperfine --warmup 1 --runs 3 -L concurrency off, 3 " pnpm exec eslint --cache --concurrency {concurrency} './**/*.{ts,tsx,graphql}' " Benchmark 1: pnpm exec eslint --cache --concurrency off ' ./**/*.{ts,tsx,graphql} ' Time ( mean ± σ ) : 2 . 516 s ± 0 . 044 s [ User: 2 . 006 s, System: 0 . 578 s ] Range ( min … max ) : 2 . 470 s … 2 . 557 s 3 runs Benchmark 2: pnpm exec eslint --cache --concurrency 3 ' ./**/*.{ts,tsx,graphql} ' Time ( mean ± σ ) : 4 . 574 s ± 0 . 037 s [ User: 6 . 710 s, System: 2 . 061 s ] Range ( min … max ) : 4 . 540 s … 4 . 614 s 3 runs Summary pnpm exec eslint --cache --concurrency off ' ./**/*.{ts,tsx,graphql} ' ran 1 . 82 ± 0 . 04 times faster than pnpm exec eslint --cache --concurrency 3 ' ./**/*.{ts,tsx,graphql} ' 今回の検証ではすべてのファイルに対するキャッシュが有効な状態で試しているので極端な例ではありますが、この場合は直列で実行したほうが良い結果を得ることができました。 ここまでの整理のために、同じオプションに加えてキャッシュが無効な場合も含めて比較してみましょう。 hyperfine --warmup 1 --runs 3 -L cache --cache,--no-cache -L concurrency off, 3 " pnpm exec eslint {cache} --concurrency {concurrency} './**/*.{ts,tsx,graphql}' " Benchmark 1: pnpm exec eslint --cache --concurrency off ' ./**/*.{ts,tsx,graphql} ' Time ( mean ± σ ) : 2 . 417 s ± 0 . 026 s [ User: 1 . 886 s, System: 0 . 534 s ] Range ( min … max ) : 2 . 391 s … 2 . 442 s 3 runs Benchmark 2: pnpm exec eslint --cache --concurrency 3 ' ./**/*.{ts,tsx,graphql} ' Time ( mean ± σ ) : 4 . 508 s ± 0 . 031 s [ User: 6 . 682 s, System: 2 . 051 s ] Range ( min … max ) : 4 . 473 s … 4 . 530 s 3 runs Benchmark 3: pnpm exec eslint --no-cache --concurrency off ' ./**/*.{ts,tsx,graphql} ' Time ( mean ± σ ) : 59 . 652 s ± 0 . 536 s [ User: 73 . 527 s, System: 10 . 505 s ] Range ( min … max ) : 59 . 221 s … 60 . 253 s 3 runs Benchmark 4: pnpm exec eslint --no-cache --concurrency 3 ' ./**/*.{ts,tsx,graphql} ' Time ( mean ± σ ) : 49 . 708 s ± 0 . 678 s [ User: 134 . 778 s, System: 34 . 085 s ] Range ( min … max ) : 48 . 982 s … 50 . 323 s 3 runs Summary pnpm exec eslint --cache --concurrency off ' ./**/*.{ts,tsx,graphql} ' ran 1 . 86 ± 0 . 02 times faster than pnpm exec eslint --cache --concurrency 3 ' ./**/*.{ts,tsx,graphql} ' 20 . 56 ± 0 . 35 times faster than pnpm exec eslint --no-cache --concurrency 3 ' ./**/*.{ts,tsx,graphql} ' 24 . 68 ± 0 . 34 times faster than pnpm exec eslint --no-cache --concurrency off ' ./**/*.{ts,tsx,graphql} ' この結果から、今回の環境では キャッシュが有効なら直列のほうが速い キャッシュが無効なら並列のほうが速い ということが言えそうです。 CI 環境への適用判断 このプロジェクトではCIでESLintを実行しているので、最後にCIでESLintの concurrency オプションを追加するべきか検討してみます。 前提として、このプロジェクトはTurborepoが導入されています。Turborepoは複数のパッケージからなるモノレポにおいて、ビルドやテストなどのタスクを効率的に実行するツールです。修正したファイルの範囲によりますが、このプロジェクトは最大で9つのパッケージに対してESLintが実行されることになります。Turborepoでそれぞれのパッケージへのコマンドを並列実行することになるため、 ESLintの concurrency オプションを使うと過剰な並列数になってしまい、良いパフォーマンスを得られない可能性がありそうです。 実際に試してみましょう。以下ではturboコマンドを経由してfmtコマンドを実行していますが、これは概ね eslint --cache --fix './**/*.{ts,tsx,graphql}' であると思っていただいて構いません。 hyperfine --warmup 1 --runs 3 -L concurrency off, 2 , 3 " pnpm exec turbo run --cache local:w,remote:w fmt -- --concurrency {concurrency} " Benchmark 1: pnpm exec turbo run --cache local:w,remote:w fmt -- --concurrency off Time ( mean ± σ ) : 4 . 561 s ± 0 . 290 s [ User: 2 . 431 s, System: 0 . 870 s ] Range ( min … max ) : 4 . 376 s … 4 . 895 s 3 runs Benchmark 2: pnpm exec turbo run --cache local:w,remote:w fmt -- --concurrency 2 Time ( mean ± σ ) : 6 . 291 s ± 0 . 075 s [ User: 5 . 689 s, System: 1 . 793 s ] Range ( min … max ) : 6 . 208 s … 6 . 353 s 3 runs Benchmark 3: pnpm exec turbo run --cache local:w,remote:w fmt -- --concurrency 3 Time ( mean ± σ ) : 6 . 322 s ± 0 . 012 s [ User: 7 . 296 s, System: 2 . 287 s ] Range ( min … max ) : 6 . 315 s … 6 . 335 s 3 runs Summary pnpm exec turbo run --cache local:w,remote:w fmt -- --concurrency off ran 1 . 38 ± 0 . 09 times faster than pnpm exec turbo run --cache local:w,remote:w fmt -- --concurrency 2 1 . 39 ± 0 . 09 times faster than pnpm exec turbo run --cache local:w,remote:w fmt -- --concurrency 3 やはり直列で実行したほうがより良いパフォーマンスを得ることができそうです。 これらの処理はGitHub ActionsでGitHubのPull-Requestに対して実行されるようにしていますが、ほとんどのPull-Requestでは一度に大量のファイルを修正することはありません。つまり多くのケースではESLintのキャッシュは大多数のファイルで有効な状態であると考えることができます。 またこのワークフローはUbuntuの4コアで実行するようにしていますが、コア数が少ないためさらなる並列化によってより良いパフォーマンスが得られる見込みは薄そうです。 実際にこのワークフローでベンチマークした結果が以下です。 hyperfine --warmup 1 --runs 3 -L concurrency off, 2 , 3 , 4 ,auto " pnpm exec turbo run --cache local:w,remote:w fmt -- --cache-strategy content --concurrency {concurrency} " Benchmark 1: pnpm exec turbo run --cache local:w,remote:w fmt -- --cache-strategy content --concurrency off Time ( mean ± σ ) : 13 . 241 s ± 0 . 038 s [ User: 41 . 594 s, System: 5 . 830 s ] Range ( min … max ) : 13 . 204 s … 13 . 280 s 3 runs Benchmark 2: pnpm exec turbo run --cache local:w,remote:w fmt -- --cache-strategy content --concurrency 2 Time ( mean ± σ ) : 31 . 019 s ± 0 . 075 s [ User: 104 . 797 s, System: 13 . 536 s ] Range ( min … max ) : 30 . 954 s … 31 . 102 s 3 runs Benchmark 3: pnpm exec turbo run --cache local:w,remote:w fmt -- --cache-strategy content --concurrency 3 Time ( mean ± σ ) : 39 . 606 s ± 0 . 037 s [ User: 136 . 718 s, System: 17 . 224 s ] Range ( min … max ) : 39 . 568 s … 39 . 643 s 3 runs Benchmark 4: pnpm exec turbo run --cache local:w,remote:w fmt -- --cache-strategy content --concurrency 4 Time ( mean ± σ ) : 48 . 413 s ± 0 . 007 s [ User: 169 . 105 s, System: 21 . 288 s ] Range ( min … max ) : 48 . 406 s … 48 . 420 s 3 runs Benchmark 5: pnpm exec turbo run --cache local:w,remote:w fmt -- --cache-strategy content --concurrency auto Time ( mean ± σ ) : 27 . 108 s ± 0 . 056 s [ User: 91 . 045 s, System: 11 . 620 s ] Range ( min … max ) : 27 . 063 s … 27 . 170 s 3 runs Summary pnpm exec turbo run --cache local:w,remote:w fmt -- --cache-strategy content --concurrency off ran 2 . 05 ± 0 . 01 times faster than pnpm exec turbo run --cache local:w,remote:w fmt -- --cache-strategy content --concurrency auto 2 . 34 ± 0 . 01 times faster than pnpm exec turbo run --cache local:w,remote:w fmt -- --cache-strategy content --concurrency 2 2 . 99 ± 0 . 01 times faster than pnpm exec turbo run --cache local:w,remote:w fmt -- --cache-strategy content --concurrency 3 3 . 66 ± 0 . 01 times faster than pnpm exec turbo run --cache local:w,remote:w fmt -- --cache-strategy content --concurrency 4 どうやらこのプロジェクトのESLintには concurrency オプションは追加せず、Turborepoによる並列化のみに留めたほうがよさそうです。 まとめ 以上、 ESLintのMultithread Lintingの導入を検討する際に検証したことでした! 今回検証したプロジェクトのCIには concurrency オプションの追加は見送りましたが、一定の条件下であれば concurrency オプションを使うことでESLintの処理を高速化することができます。しかしその効果は、対象のファイル数、実行環境、キャッシュの有無などによって大きく異なります。導入する前に対象の環境や用途に合うか検証することをオススメします。 他にもチーム内ではESLintの一部のルールを oxlint に置き換えて高速化を試みる動きもあります。良い結果が出てより高速なCI環境が手に入るといいですね! それでは!
はじめに こんにちは、カイポケのリニューアルプロジェクトを担当しているエンジニアの菅原です。2023年12月に入社し、現在はフロントエンドエンジニアとして機能開発を行っています。 最近、Claude CodeやGitHub CopilotなどのAIエージェントが注目されており、弊社でも活発にAIエージェントを活用した開発が行われております。 私が所属しているチームでも、AI活用の取り組みの一環として、 フロントエンドの実装自動化 に挑戦しました。具体的には、二週間のスプリント期間内で実施するすべてのフロントエンドタスクを、AIエージェントによる自動実装で完成させることを目標とした実験を行いました。 結論から申し上げると、完全な自動化には至らなかったものの、適切な仕組みを整備することで実装プロセスの大幅な効率化を実現することができました。 本記事では、この取り組みを通じて得られた知見と課題、そしてAIエージェントによる実装自動化の現実的な可能性について紹介させていただきます。 取り組みのモチベーション カイポケのリニューアルプロジェクトでは、開発手法としてLeSS(Large Scale Scrum:大規模スクラム)を取り入れており、隔週でスプリントを回しています。LeSSのイベントである、リファインメントを通じて、複数チームに跨ったPBI(ブロダクトバックログアイテム)の分割や曖昧な要求を詳細化することで、スプリント活動中にチームが担当するPBIの不確実要素が下がった状態を実現できています。 また、スプリント期間中もチーム内でモブプログラミングや実例マッピングといった手法を活用して、チームが担当するPBIの要求をより詳細化していき、SBI(スプリントバックログアイテム)というPBIを完了させるために取り組む必要があるタスクのリストに分割しています。スクラムのプラクティスの1つとして、SBIを1日以内に終わる単位で分割することが推奨されており、開発者が実装するタイミングでは仕様が明確になっているため、スムーズに開発できるケースが多くなっています。 このような状況の中で、私はAIエージェントを活用しつつ日々の開発に取り組んでいましたが、要求が明確なため実装後に期待するアウトプットのイメージが持ちやすく、ある程度はAIエージェントに実装を任せても十分な品質のコードを出力できていると感じていました。 そのため、弊プロジェクトで採用しているLeSSによるPBIの不確実性を下げる取り組みと、AIエージェントによる自動実装には強い親和性があるという仮説を持ちました。そこで思い切って、私が担当する一スプリント内のすべてのタスクをAIエージェントにより実装させることで、 実装をどこまで自動化できるか という挑戦を行うことにしました。 LeSS導入時の経緯は過去記事をご参照ください。 自動化の概念図 今回の取り組みでは、スプリント期間中のすべての開発プロセスを自動化するのではなく、初期の実装とPRレビューの指摘事項への修正を対象に自動化することとしました。 自動化対象のイメージは以下の概念図を参照してください。 取り組み内容 1. 設計ドキュメントからAIエージェントがdraft PRを自動作成 まず、AIエージェントによる実装自動化の第一歩として、FigmaのコンポーネントURLと「このコンポーネントを実装して」のような簡潔な指示を出して、AIエージェントに実装を任せてみることから始めました。 しかし、このアプローチでは以下のような問題が発生し、生成されたコードは一見動作するものの、期待値を満たしておらずに大幅な修正が必要になるという結果になりました。 デザインシステムとの不整合 : デザインシステムのコンポーネントやカラー、フォントサイズなどの定義を無視した、独自の実装になってしまう インタフェース定義の不備 : 他のコンポーネントとの連携に必要なProps定義やGraphQLスキーマの型定義が不適切になってしまう 振る舞いの実装ミス : UIの細かな状態変化やユーザー操作に対する振る舞いが期待値と異なる実装になってしまう これらの問題を解決するため、スプリント活動でアウトプットした設計ドキュメントを基に、実装時に必要な情報を構造化して提供する方針にしました。 MCPを活用してデザインシステムに準拠 デザインシステムとの不整合を解消するため、弊社の内製Figma MCPとデザインシステムMCPを活用したアプローチを採用しました。これにより、AIエージェントは以下のような情報を参照しながら実装を行えるようになりました。 デザイントークン : カラー、スペーシング、フォントサイズなどの基本的なデザイン要素を参照 コンポーネント定義 : 各UIコンポーネントで定義されたPropsを参照 この仕組みにより、AIエージェントが生成するコンポーネントは、デザイナーが意図した見た目と動作に近い状態で実装できるようになりました。 弊社内製のMCPの実装については以下記事で詳しく解説しているので、併せてご参照ください。 インタフェース定義の標準化 実装するコンポーネントのインタフェース定義やGraphQLスキーマの定義が曖昧な状態では、AIエージェントは柔軟に実装してくれます。しかし、この「柔軟性」が問題となり、毎回異なる結果を出力してしまうことから、実装予定の他のコンポーネントとの連携が取れない実装になってしまうという問題がありました。 この問題を解決するため、スプリント活動の設計フェーズで明確になった仕様を基に、事前にインタフェース定義を固定し、AIエージェントへのインプット情報として明示的に提供するようにしました。 以下はインプットとして提供する情報の例です。 コンポーネントを実装するディレクトリの例 src/services/careReceivers/tableRow/TableRow.tsx にコンポーネントを実装 コンポーネントのPropsの例 type Props = { id : string ; name : string ; } ; 利用するGraphQLスキーマの例 fragment CareReceivers on User { id name } UIの振る舞いの構造化 AIエージェントが生成したコンポーネントは、見た目は正しく実装されているものの、ユーザーの操作に対する反応や状態変化が仕様と異なることがありました。 この課題に対しては、スプリント活動の実例マッピングで整理したUIの振る舞いを、Given When Then形式で構造化し、AIエージェントにテスト駆動開発で実装させる方針を採用しました。 具体的には、以下のような流れで実装を行います。 振る舞いの構造化 : 実例マッピングの結果をGiven When Then形式で記述 テストの実装 : AIエージェントがその仕様に基づいてテストコードを実装 コンポーネントの実装 : テストがパスするまでコンポーネントを繰り返し修正 UIの振る舞いの例(Given When Then形式で記述) Given : 利用者一覧画面が表示されている状態で When : 利用者のチェックボックスをチェックすると Then : ヘッダーにチェックした利用者件数が表示されること このアプローチにより、AIエージェントが生成するコンポーネントは、見た目だけでなく動作も仕様通り実装されるようになりました。 プロジェクト固有のコンテキストの提供 上記の主要な課題への対策に加えて、AIエージェントがプロジェクトの既存実装パターンを理解し、一貫したコードスタイルで実装できるよう、以下も補完情報として加えました。 リファレンス実装のディレクトリパス コーディングガイドラインのファイルパス これらの構造化されたインプット情報を整備した結果、AIエージェントによる実装品質が安定するようになりました。 2. インラインレビューによるAIエージェントの自動修正 上記のアプローチにより、実装品質が安定したものの、インプットの内容の不備やコンテキストの欠落により、AIエージェントが生成したdraft PRをそのまま商用環境に適用することは厳しいことがわかりました。 そこで、draft PRで不十分な箇所については、人手でのPRレビューにより修正する方針としました。 最初のアプローチとして、AIエージェントが GitHub CLI を活用してPR reviewの内容をチェックして修正するようにしていましたが、以下の課題がありました。 すでに解決済みのレビューコメントも取得してしまい、フィードバックの回数が増えると適切な修正が行われなくなる レビューコメントに対して、AIエージェントが修正した内容をチェックするのに手間取り、指摘内容が適切に修正されているか確認しづらい そこで、効率的なPRレビューを実現できるように GitHub GraphQL API を活用して、以下のツールを持つ簡易的な自作GitHub MCPサーバーを作成し、レビューコメントの修正を行うようにしました。 get_pull_request_review_comments : 未解決かつ参照元のコードが最新のレビューコメントのみを取得するツール reply_to_fixed_commit_in_pull_request_review_thread : レビューコメントに対して修正内容の完了と修正した対象のコミットハッシュを通知するツール これらのツールを活用することで、AIエージェントが以下のプロセスでインラインレビューの指摘事項を修正することができたため、コードを期待する品質まで改善させることができました。 レビューコメントの取得 : get_pull_request_review_comments でPRの未解決コメントを一括取得 修正内容の特定 : AIエージェントがコメントの内容を解析し、必要な修正を特定 コードの修正 : 指摘事項に基づいてAIエージェントが自動でコードの修正を実行 修正完了通知 : reply_to_fixed_commit_in_pull_request_review_thread で修正コミットと修正内容を報告 具体的なMCPツールの実装イメージは以下を参考にしてください。 MCPツールの実装イメージ 1. get_pull_request_review_comments PRのレビューコメントを構造化されたデータとして取得するツールです。 以下のコードブロックでは、現在の作業ブランチ(draft PRを作成したブランチ)を入力値として渡すと、未解決のレビューコメントのファイルパスとスレッドを返す仕組みを表現しています。 server.registerTool( "get_pull_request_review_comments" , { description : "Get comments from pull request review threads" , inputSchema : { branchName : z.string().describe( "Branch name of the pull request" ), } , outputSchema : { filePaths : z.array( z.object( { filePath : z.string().describe( "File path of the review thread" ), reviews : z .array( z.object( { threadId : z.string().describe( "ID of the review thread" ), startLine : z .number() .nullable() .describe( "Start line of the review thread" ), endLine : z .number() .nullable() .describe( "End line of the review thread" ), comments : z .array(z.string()) .describe( "Comments in the review thread" ), } ), ) .describe( "Reviews in filePath" ), } ), ), } , } , async ( params ) => { // 未解決のPRレビューコメントを構造化されたデータとして返却する処理 } , ); リクエストの例 branchName: 現在の作業ブランチ(draft PRを作成したブランチ) { " branchName ": " feature/current-branch " } レスポンスの例 filePath: レビュー対象のファイルパス reviews: レビューのスレッドID、コメントの範囲、コメントの内容 { " filePaths ": [ { " filePath ": " src/components/UserList.tsx ", " reviews ": [ { " threadId ": " threadId1 ", " startLine ": 15 , " endLine ": 20 , " comments ": [ " 型定義が不十分です。Propsの型を明確に定義してください。 ", " ユーザビリティの観点から、エラーハンドリングを追加したほうが良いです。 " ] } ] } ] } 2. reply_to_fixed_commit_in_pull_request_review_thread レビューコメントに対して修正完了の返信を自動で行うツールです。 以下のコードブロックでは、 get_pull_request_review_comments で取得したレビューのスレッドIDと修正したコミットハッシュ、修正内容を入力値として、対象のレビュースレッドに対して修正内容を通知する仕組みを表現しています。 server.registerTool( "reply_to_fixed_commit_in_pull_request_review_thread" , { description : "Reply to a fixed commit in a pull request review thread" , inputSchema : { threadId : z.string().describe( "ID of the comment to reply to" ), commitHashes : z .array(z.string()) .min( 1 ) .describe( "Array of commit hashes of the pull request" ), message : z.string().describe( "Custom message to include in the reply" ), } , outputSchema : { result : z.object( { success : z.boolean().describe( "Whether the reply was successful" ), body : z.string().describe( "Content of the reply" ), createdAt : z .string() .describe( "Timestamp of when the reply was created" ), } ), } , } , async ( params ) => { // レビューのスレッド単位で修正内容を返信する } , ); リクエストの例 threadId: レビューのスレッドID commitHashes: レビューコメントに対して修正したコミットハッシュ message: 修正内容 { " threadId ": " threadId1 ", " commitHashes ": [ " ea9f557c44b545b93d7f86fcc7cb796c77022367 " ] , " message ": " ご指摘いただいた点を修正しました。型定義を追加し、エラーハンドリングも実装しています。 " } レスポンスの例 threadIdで指定したスレッドに対して、レビューコメントを返す まとめ 本記事では、LeSSによってPBIの不確実性が低減された状況とAIエージェントによる自動実装に親和性があるという仮説のもと、スプリント期間中のフロントエンド実装自動化に挑戦した取り組みについて紹介させていただきました! 完全な自動化には至らなかったものの、この取り組みを通じて、以下の仕組みによりAIエージェントによる実装の大幅な効率化を実現できました。 スプリント活動でアウトプットした設計情報を、AIが理解しやすい形式に整理し、設計ドキュメントを構造化 独自のGitHub MCPを活用して、PRレビューコメントの自動取得と修正完了通知の仕組みを実装し、自動修正フローを構築 さらに、弊社内製のFigma MCPやデザインシステムMCPとの連携により、デザインシステムに準拠した実装を自動生成する体験も実現しました。 一方で、完全な自動化を実現するには、まだまだ以下のような課題があることもわかりました。 AIエージェントが安定した出力を行うための設計ドキュメントの構造化が必要 複雑なビジネスロジックや例外処理では、人手による詳細な指示やレビューが必要 AIが解釈しやすい形式でのコーディングガイドライン整備が必要 現状では「完全自動化」よりも「効率的な協働」が現実的であることがわかりました。今後はこれらの課題を解消しつつ、人とAIがより良く協働できる開発体験の実現を目指していきたいと考えています。
こんにちは。介護・医療・障害福祉・保育の求人サイト「ウェルミージョブ」のQAを担当している林です。 ウェルミージョブは、2025年7月にカイゴジョブからリブランディングしてサービス提供を開始しました。 私はアジャイルな開発チームの中で、テストをこなすだけでなく、開発チーム全体でプロダクト・サービス品質を向上すべく日々挑戦しています。 今回の記事では、QA担当の私が開発チームにポストモーテムを導入し、チームでの実践に至るまでの経緯と、その具体的な進め方についてお伝えします。 0. はじめに エス・エム・エスのQA組織では、Value(行動指針)として「チームで品質保証」を掲げています。 これは、介護/障害福祉事業者向け経営支援「カイポケ」のQAチームにて策定されたもので、ウェルミージョブのQAチームでも同じマインドを共有しています。 QA組織の行動指針を言語化した取り組みについては、以下の記事をご覧ください。 tech.bm-sms.co.jp 「チームで品質保証」の範囲はQAに留まらず、開発・デザイナー・PdM・事業メンバー・運用メンバーなどと幅広く協同することを想定しています。 横断的に「チームで品質保証」を実践している事例については、以下の記事をご覧ください。 tech.bm-sms.co.jp 1. QAの私がポストモーテムにチャレンジした経緯 チームでの品質保証活動における「3つの課題」 私はかねてより「チームで品質保証」のもと、開発チーム全体で質の高い原因分析をして再発防止に取り組みたいと思っていました。 しかしながら、以下のような課題感がありました。 QAが実施する不具合分析やインシデントの振り返りが、開発メンバーを巻き込んでの活動に繋げづらい 過去に開発メンバーでインシデント振り返りやポストモーテムを行った実績もあるが、経験値や関心度はメンバーによって差がある 同じ方向をむいて原因分析・再発防止を検討できる基盤がない 私をポストモーテムへの挑戦に導いた「3つの決め手」 課題を抱えていた私に、ポストモーテムについて触れる機会が次々とやってきました。 そして、以下の決め手により、ポストモーテムへ挑戦したい気持ちが固まっていきました。 チームで同じ方向を向ける「指南書」の存在 他チームの成功事例による「道しるべ」 「QAの業務」ではなく「チームの活動」にできる可能性 以下に、それぞれの決め手についてお話しします。 1. チームで同じ方向を向ける「指南書」の存在 同僚のQAエンジニアが作成したドキュメント中に、ポストモーテムの指南書ともいえるものを見つけました。 その中には「直接的原因・間接的原因・動機的原因」を切り分けた分析アプローチの例示と、フィッシュボーンチャートがありました。 私は「これを使えばチームで同じ方向を向いて活動できそう!」と直感しました。 「直接的原因・間接的原因・動機的原因」を切り分けた分析アプローチ 「原因」という言葉は意味が広く、人によってイメージするものが異なりがちです。「直接的原因・間接的原因・動機的原因」を分けて考えることで、チームメンバー間のイメージをすり合わせが容易になり、チームで同じ方向を向いて分析を進めることができます。指南書では、「直接的原因・間接的原因・動機的原因」について以下のように身近な例でわかりやすく説明されていました。 例:カロリーの摂りすぎで肥満になり、⚪︎⚪︎病(インシデント)になった 起きたこと -> 〇〇病 直接的原因 -> 肥満(hogehoge数値の増加) 間接的原因 -> カロリーの摂りすぎ 動機的原因 -> 日々の仕事でストレスがたまっており、過食の傾向があった フィッシュボーンチャート フィッシュボーンチャートは、ある問題(結果)とその原因の関係を、魚の骨のような形で整理・可視化するための図です。ある問題(魚の頭)は、どのような原因(骨)から起きているのか?をひと目で理解することができます。 2. 他チームの成功事例による「道しるべ」 他開発チームにおいて「ポストモーテムを重ねた結果、検討の観点・深さがよくなってきて、品質向上のプロセスが磨かれている」との情報をキャッチしました。これは、まさに私の目指したい姿です。 また、他チームにてポストモーテムのフォーマットが確立していることも確認できたため、フォーマットをそのまま流用して省コストでチャレンジできそうでした。 3. 「QAの業務」ではなく「チームの活動」にできる可能性 私は、チーム全体で活動をするにあたり「QA業務を開発メンバーに協力してもらう」ではないやり方を模索中でした。 ポストモーテムは、当時のウェルミージョブ開発チーム内では「QA(または開発)がやるもの」という概念がない状態だったため、「これならQAの業務ではなくチームの活動にできそう!」と感じました。 そして、ついにポストモーテムへ挑戦する日が訪れました。 2. ポストモーテム実施 初回チャレンジ ステークホルダへ原因や再発防止について報告が必要な状況となったため、私から「今回はポストモーテムにチャレンジしてみませんか?」と開発チームへ提案しました。 ポストモーテムについて、社内における他チームでの実績や参考にできる情報が多くあることを伝え、開発チームの賛同を得ました。 誰がファシリテートするかについてはもちろん、ポストモーテムへの挑戦にワクワクしている私が引き受けました。 以下、初回チャレンジのサマリです。 活動のステップ 資料たたき(ステータス・サマリ・タイムライン・影響・原因・対応・アクションアイテム)作成:QA(私) 読合せ会1:開発・QA・PdM・事業メンバー 読合せ会2:開発・QA・事業メンバー 改善アクション実行:開発・QA 大事にしたこと チーム全体で同じ方向を向いて原因分析に取り組むこと 効果的かつ実現可能な再発防止策を導き出すこと 次回以降、私ではない他のメンバー(特に、QAではなく開発メンバー)がチャレンジできるように敷居を下げること チャレンジ結果 【◎】「直接的原因・間接的原因を切り分けた分析アプローチ」によりチーム全体で方向性を合わせ、解像度を高めて効果的な分析ができた 【△】読合せ会が初動の話で盛り上がり、原因分析の話が十分にできなかったため、別日に読合せ会2を追加開催することになった 【△】後から資料を整理する時間がなく、資料が読みづらいままになってしまった 【◎】改善アクションを、QAタスクではなく開発チームのタスクとして進められている このように、ポストモーテム初回チャレンジは概ね成功といってよい形で実施することができました。 さて、このポストモーテムの活動を開発メンバーへ展開していきたい…と思っていた矢先、予想外に早く、その時は訪れてしまいました。 2回目チャレンジ 初回チャレンジから間を空けず、ポストモーテムの成功体験が記憶に新しいタイミングで、開発チームへ2回目のポストモーテム実施を提案したところ賛同が得られました。 「ぜひ開発メンバーにチャレンジしてほしい、私が伴走する」とファシリテーターについて持ち掛けたところ、ポストモーテム未経験の開発メンバーに立候補してもらえました。 以下、2回目チャレンジのサマリです。 活動のステップ 資料たたき(ステータス・サマリ・タイムライン・影響・原因・対応・アクションアイテム)作成:開発(伴走:QA) 原因分析の分科会:開発・QA(主要メンバーのみ) 読合せ:開発・QA・事業メンバー・運用メンバー 改善アクション実行:開発・QA 大事にしたこと 私はできるだけ裏方に徹すること チーム全体で同じ方向を向いて原因分析に取り組むこと 効果的かつ実現可能な再発防止策を導き出すこと チャレンジ結果 【◎】QAが行った品質活動に、開発メンバー主導でチャレンジした実績ができた 【◎】原因分析を分科会で事前に実施し、課題が一定クリアになった状態で読合せができた 【◎】ポストモーテム前提でインシデント対応中に時系列を記録できていたことで、情報収集の負荷が軽減できた 【△】同じ方向をむいて原因分析するために重要なフィッシュボーンチャート等がカットされてしまったため、私にて再掲 【△】ポストモーテムの形式にとらわれすぎて、読合せ会の前半が資料の読み上げになってしまった 【△】後から資料を整理する時間がなく、資料が読みづらいまま 【◎】改善アクションを、QAタスクではなく開発チームのタスクとして進められている このように、2回目のポストモーテムも概ね成功といってよい形で実施できたのではと思います。 特に原因分析について、分科会としてメンバーを絞って事前に実施したことで、必要十分な工数をかけて余計な圧などがない環境で議論ができ、より確度の高い分析ができたと感じています。 また、改善アクションについて、開発メンバーにて迅速に対応がなされて一部改善効果が出ており、効果的かつ実現可能な再発防止が進められています。 3. おわりに その後、報告書が必要となる大規模のインシデントは発生していませんが、小規模のインシデント対応においても開発チームのメンバーから「ポストモーテムしましょうか」と声が上がり、ポストモーテムの実施が定着しつつあります。 また、ポストモーテムを意識した情報整理も意識されるようになり、別のインシデント対応において他システムの開発チームとの連携にも役立ちました。 今回のポストモーテムへのチャレンジは、今後の更なる「チームで品質保証」への取り組みの礎となると大いに期待しています。 今回のチャレンジができたのは何よりも、日ごろから開発・QA・デザイナー・事業メンバーが一丸となってアジャイルなチーム開発を進めていることにあります。 チームメンバーである塩井さんの記事『社会課題に取り組みたいRuby大好きエンジニアがセカンドキャリアにエス・エム・エスを選んだ理由』の中で「開発に責任感を持って真摯に向き合い、ごく自然にお互いに助け合うチームメンバー」とあるように、ウェルミージョブの開発チームでは、チーム全体へ働きかける形での品質向上へのチャレンジが歓迎されています。 tech.bm-sms.co.jp これからも私は「チームで品質保証」のもと、異なる専門性を持つメンバーと協力してチーム全体で品質の向上を目指すべく、チャレンジを続けます。 告知! ウェルミージョブの開発をリードする @moro が、この度「Kaigi on Rails 2025」にて初日のKeynote Speakerを務めます。 一昨年のKaigi on Rails 2023、そして去年のKaigi on Rails 2024でも大好評を博した@moroの基調講演にどうぞご期待ください! Kaigi on Rails 2025 Keynote: dynamic! 昨年までの発表 Simplicity on Rails - RDB, REST and Ruby / MOROHASHI Kyosuke - Kaigi on Rails 2023 Identifying User Identity / MOROHASHI Kyosuke - Kaigi on Rails 2024
皆さん、こんにちは! エス・エム・エスの人材紹介開発グループでマネージャーをしている @kenjiszk です。私は2023年4月に入社し、気づけば3年目に突入しました。今回は、私たちのグループが新たに始めたオフラインイベントについてご紹介します。 なぜオフラインイベント? エス・エム・エスの開発組織はフルリモートで業務を行っているため、実はまだ一度も顔を合わせたことのないメンバーが多くいました。特に九州や関西地方など遠方に住んでいるメンバーもいるため、気軽にランチをするということすら難しい状況です。 このような状況下で、私たちのグループには「チーム間のつながりが希薄である」という課題がありました。各チームは、それぞれのサービスごとに少人数のエンジニアで構成されており、日常的な業務や開発についてはこのチームの中で解決することが多いです。各チーム内での会話や議論は非常に活発ですが、チームを跨いだ議論や交流はあまり多くありませんでした。 なぜ横のつながりを大事にしたいのか? 私たちのサービスは、看護師・介護職・保育士など対象とする従事者によってサービスとチームが分かれていますが、それぞれに求められる技術的な要件やアーキテクチャは似ている部分があります。チームに閉じずに、横断的なコミュニケーションが活発になることで、自分たちが困っていることは実は他のチームが解決してくれていた、とか、自分たちが行っていることが他のチームの助けになった、ということは往々にして起こり得ます。 オンラインで機会を作ってもなかなか難しい問題 オンラインでもチームを横断したような雑談の機会や、他チームのメンバーの人となりがわかるようなLT(ライトニングトーク)を企画していましたが、偶発的にチームを横断した雑談が生まれるような雰囲気の醸成はなかなか難しいと感じていました。 物理的な距離を越えて、心の距離を縮める試み この課題を解決するため、私たちはまず「物理的に会ったことのないメンバーをなくす」ことに焦点を当てました。そして、お互いの精神的な壁を低くすることを目指し、初のオフラインイベントを企画・開催しました! イベントでは、「マシュマロチャレンジ」というチームビルディングゲームを行いました。このゲームは、パスタ、テープ、ひも、マシュマロを使い、自立可能なタワーを作るというシンプルなルールながら、チームの創造性、問題解決能力、そしてコミュニケーション能力が試されます。最も高いタワーを作ったチームが勝利となります。 普段話す機会のないメンバー同士が自然に交流できるよう、チームはランダムに編成しました。初対面のメンバーも多い編成でしたがどのチームもお互いに協力しあいタワーを作りました。 今回一番成績の良かったチームは、71cmのタワーを完成させることができました(ちなみに世界記録は99cm)。 マシュマロ・チャレンジの概要は以下の動画で確認できます。 Build a tower, build a team | Tom Wujec チームリーダーによるパネルディスカッション マシュマロゲームで会場が温まった後には、各チームのリーダー4名によるパネルディスカッションを実施しました。ここでは、現在取り組んでいる課題や、今後挑戦していきたいことなどについてざっくばらんに語ってもらいました。 普段は聞くことのできない他のチームの取り組みやリーダーたちの熱い想いに触れることができ、参加者からは「とても刺激になった」「視野が広がった」といった声が上がりました。リーダー陣のリアルな声は、今後の業務へのモチベーション向上にも繋がったことと思います。 半年に一回の開催で継続していきます イベント後のアンケート結果は、概ね好評でした!「普段話さないメンバーと交流できて楽しかった」「他チームのことが知れてよかった」といったポジティブな意見が多く寄せられ、このイベントがチームの絆を深める上で非常に有効であったことを実感しました。 リモートワークが主流の今、オフラインでの交流はより一層貴重な機会となります。次回以降もメンバー間の交流を促進し、より強固なチームを築いていけるようなイベントを継続的に開催していく予定です。 今回はリモートワークのデメリットについてスポットライトを当てましたが、リモートワークにはメリットがたくさんあり今後も良い形で続けていきたいと考えています。この取り組みを通じて、私たちの会社がどんな会社なのか、少しでも皆さんに興味を持っていただけたら嬉しいです。