エンジニアの内藤です。LIFULL HOME'Sの売買領域を支えるエンジニアチームのマネジメントを担当しています。 弊社では「ネガポジミーティング」と称し、課題を出し合う「ネガティブミーティング」と課題の解決策を決める「ポジティブミーティング」をセットで実施しています。 前回「 ネガティブミーティング 」を実施し、今回はその対となる「ポジティブミーティング」を企画し実施したので、そちらを紹介したいと思います。 ネガポジミーティングとは ネガティブミーティングとは ポジティブミーティングとは ワークの流れ やってみた結果 まとめ ネガポジミーティングとは ネガティブミーティングとは ネガティブミーティングは課題だけを挙げるミーティングで解決策などは議論しない 課題を出すことだけに集中するため、普段だと言いづらい反対意見や代替意見も思い切って伝えることができる ポジティブミーティングとは ネガティブミーティングで出た課題の解決策を決めるミーティング 出た意見の良し悪しは評価せず、まずは提案自体に感謝する 実行する解決策を決めたら「誰が」「なにを」「いつまでに」を決める ワークの流れ 今回のワークでは前回と同じチームに分かれ、以下の流れに沿ってポジティブミーティングを実施しました。 ネガティブミーティングで出た課題から解決したい課題を選択する 解決案を出し尽くす 出た解決策をブラッシュアップして、具体的に「なにをするのか」決める 解決策やそこに至った過程を全体に共有 本来は「誰が」「いつまでに」も決めるべきなのですが、確保した時間では足りなそうでしたので解決策を決めるところまで実施することにしました。 ネガティブミーティングでは悲観的にならず笑顔で終えられるしくみとして、チーム内で最も共感された課題を川柳(または短歌)にまとめるような工夫をしました。 ポジティブミーティングではそのような配慮は不要だと考え、目的である課題解決に向けた実現性のある解決策が立案されることに注力することにしました。 具体的には自分たちで実行できる手段・実行するのに現実的なコストであり、すぐに動きだせる解決策が出せるように工夫をしました。 そこでロジックツリーを利用して課題の要素を分解しながら掘り下げ、その各要素に対する部分的な解決策を出すことで多くの解決案を出す方法で実施してみました。 やってみた結果 40分をワークの時間に充てましたが、ロジックツリーを利用して20ぐらいの要素に細分化するチームなどもあり解決策を出し尽くすには少し時間が足りなかったと思いました。 しかし、ブラッシュアップされた解決策はしっかりとエンジニア特有の視点で捉えられた実現性のある解決策となっていました。 例えば、「期間終了後のABテストが放置されがち」という課題に対して「AB実装時に本実装(AはrevertPR,Bの実装PR)を用意する」という解決策となりました。 「期間が空きすぎない方が実装が頭に残っているので本実装等の対応も早い」などエンジニアでないと気付き難い点も考慮した上での解決策の選択で、非常に有益なワークになったと感じました。 また、ロジックツリーによる要素の分解では、「本実装が計画に入っていない」「企画のモチベーション」など解決策が他者任せになりそうな要素もありましたが、期待通り自分たちで実行できる部分にフォーカスした解決策が選択されていました。 ロジックツリーの例 その他にも「俗人化しているプロダクトの開発効率が悪い」という課題に対して「知見共有会」「readmeを充実化」「できるところの自動化」などエンジニアらしい解決策が出ていました。 まとめ ロジックツリーを利用して課題を細分化することで、狙い通り自分たちで実行できる手段・実行するのに現実的なコストのすぐに動きだせる解決策を出せたワークになったと思います。 今回は解決策を決めるところまででしたが、「誰が」「いつまでに」も決めて実行していくことで課題を解決しより良い組織や職場環境にしていきたいと思います。 最後に、LIFULL ではともに成長していける仲間を募集しています。よろしければこちらのページもご覧ください。 hrmos.co hrmos.co
こんにちは。私はLIFULLで LIFULL HOME'S不動産査定 と ホームズマンション売却 の開発をしている新卒二年目の韓国人の開発者、ジョン ヨンソクです。入社当初に比べて、日本語によるコミュニケーションには慣れてきましたが、一方で成長が止まったのではないかと感じています。 そこで、これまでのやり方を振り返り、コミュニケーションに対する工夫や言語的な困難を克服するための方法を考え、さらなる成長を目指す話を共有したいと思います。 振り返り 基準を定める 捨てる要素 敬語 不安 重要な要素 相手を配慮 「結論 → 理由 → 事例」話法 課題 言語化能力の向上 日本語の専門用語を習得 まとめ PR 外国籍のお部屋探し 仲間募集 振り返り 日本語で仕事をするようになってから、ある程度の時間が経ち、徐々に慣れてきたと感じます。 年数が経過するにつれて、業務範囲が自然と広がり、より高度なコミュニケーション能力が求められる場面が増えてきました。また、今期からの状況の変化もあり、自身のコミュニケーション能力についてあらためて振り返ってみると、成長しているのかどうか疑問を感じました。 今までは、外国人としてコミュニケーション能力を上げるために、分からない専門用語とカタカナ語を暗記することに優先順位を置いてきました。入社当初は、この方法によってコミュニケーション能力が向上していることを感じられました。 しかし、このやり方のせいで私の中でコミュニケーションにおいて重要なことは完璧な日本語になっていました。チャットを送る際には、間違った日本語を使っていないかという心配で、正しい日本語を求めて調べることに時間を使うことが多かったです。結果的に円滑なコミュニケーションになっていないことに気付き、円滑なコミュニケーションになるための基準を定めました。 基準を定める 捨てる要素 敬語 敬語は、ある程度理解はしているつもりですが、正しい使い方に自信が持てないことが多くあります。 そのため、正確に区別して使用することは非常に難しく、文章を作るのに倍以上の時間がかかり、使用する際に不安を感じることがあります。 しかし、大切なのは円滑なコミュニケーションです。外国人という立場を活かし、少し間違っても良いという気持ちで、すばやく回答することを優先することにしました。 敬語は、現在持っている言語能力を十分に活用するために捨てる要素であり、この問題は今後解決すべき課題です。 不安 日本語を間違って使っているかもしれないという不安があります。この不安をなくすため、完璧な文章を作ろうとする傾向があります。チャットで何か文章を送信する際にも、何度も調べたり修正したりして時間がかかってしまうことがあります。 しかし、口頭で話すときは、不安を感じる暇もなく会話が流れます。口頭での会話のように、チャットでも不安を感じる暇を与えずに、いったん文章を送信することを意識することにしました。 一方で、内容がめちゃくちゃになることもありますが、それでも不安をなくすことが目的ですので、この問題も今後解決すべき課題です。 重要な要素 相手を配慮 捨てる要素が2つあるため、つい不適切な表現をしてしまうことがあります。そのため、お互いに気持ちよいコミュニケーションのためには、相手に配慮する心構えが最も重要だと考えます。 たとえば、コードレビューの際には、相手のコードを尊重し、ネガティブなコメントは避けるように心がけます。また、修正が必要な場合は、命令形ではなく提案形で伝えるようにしています。"いかがでしょうか"という表現をよく使います。 一方で、相手を配慮することが重要ですが、やり過ぎると不明瞭な表現になってしまうことがあります。明確な伝え方が必要な場合もありますので、過去の私の表現を振り返り、良い例を探して改善していく努力が欠かせません。 「結論 → 理由 → 事例」話法 この話法は、文書やプレゼンテーションなどで重要な内容を効果的に伝えるために役立ちます。 まず、結論を述べることで聞く人が主要な内容をすばやく理解でき、その後に理由や背景を説明することで聞く人がなぜその結論が導かれたのかを理解できます。 最後に、具体例を挙げて内容を具体化することで、聞く人がより明確に理解できます。 ただし、この方法が常に最適なわけではありません。たとえば、長い話をする場合には、順番に話す方が適しているかもしれません。また、状況によっては詳細が必要な場合もありますので、そのような場合には、より詳細を含めて話す方が適切かもしれません。 したがって、これらの方法は状況に応じて適切に使用する必要があります。しかし、通常の状況では、この方法がコミュニケーションに効果的であることが多いため、私もこの方法で話すことが多いです。 課題 コミュニケーションにおいて基準を定めて、実行しました。結果、チャットでのコミュニケーションは以前に比べて迷いも少なく、スムーズになったと感じています。 ただし、リアルタイムで反応が必要な会議などのコミュニケーションにおいては、理解が遅れたり、発言する機会を逸したりするなどの課題が残っています。これらは今後克服しなければならない課題であり、そのために2つの方向性を考えました。 言語化能力の向上 1つ目は言語化を練習することです。 私の意思を迅速に整理し、明確に伝える能力を身につけるためには、言語表現の練習が必要だと考えました。 私は個人ブログを開設し、韓国語で何でも書く練習を始めました。言語表現の練習が目的であれば、母国語であっても問題ないと思います。もちろん、慣れてくると日本語で作文することもできるようになるでしょう。 日本語の専門用語を習得 1年間で、技術的に足りない部分をAWSとLinux関連の勉強で補い、資格を取得しました。試験はすべて日本語で受けました。理由は、日本語の専門用語が理解できない時も多い一方、どのように勉強すれば良いか悩んでいたため、この機会に習得できると考えました。 業務に関連する勉強をする際には、日本語で並行して勉強することで、専門用語の習得につながると考えました。次に取り組むアクションとして、年に1冊の専門書籍を日本語で読んで文章で整理することを考えています。 まとめ 外国人である私が日本語によるコミュニケーションに慣れるため、これまでのやり方を振り返り、コミュニケーションへの工夫をしました。 具体的には、完璧な日本語にこだわらず、相手に配慮しながらも明確な表現をすることを心がけ、迅速な回答をすることを優先するようにしました。 私が定めた基準を実行するためには、自分が置かれている環境も重要だと考えます。LIFULLでは、率直で建設的なコミュニケーションを重視し、誰かが成長のための行動に対しては支援を惜しまない企業文化があります。 何かを実行する際に躊躇することなく、行動できる企業文化は 実際の業務 を通じて実感できました。そのため、本当は欠かせない要素たちを捨て、行動するなどの取り組みが試しやすかったと思います。 今後も、言語化能力の向上と日本語の専門用語の習得を目指し、今後克服すべき課題として取り組んでいくつもりです。 PR 外国籍のお部屋探し 一人で部屋を探す際、外国籍であることが理由で何度か断られた経験があります。外国籍などの普通でないバックグラウンドがあると、偏見を持たれることがあるのだと感じました。 そんな方々に向けて、さまざまなバックグラウンドの方に理解があり“ありのまま”住まい探しの相談ができる不動産会社検索サイト「LIFULL HOME'S FRIENDLY DOOR」を紹介します。 お部屋探しの際は、ぜひご利用ください。 actionforall.homes.co.jp 仲間募集 最後に、LIFULL では一緒に働く仲間を募集しています。よろしければこちらのページもご覧ください。 hrmos.co hrmos.co
こんにちは。エンジニアの渡邉です。普段はLIFULL HOME'Sの売買領域のエンジニアチームにて開発を担当しています。好きなApache SolrのAPIはJSON Facet APIです。 今回はLIFULL HOME'Sの画像変換サーバの構成を見直し、アプリケーションの再構築並びに基盤刷新を行い、コスト面、性能面、運用面での改善を行った話をさせていただきます。 画像変換サーバの特性 開発における課題 課題1: 開発しづらいアプリケーション 課題2: インフラリソースの最適化の余地の向上 実際にやったこと 実際の画像変換サーバを読み解く コンテナベースに置き換える 実行基盤をEC2からKubernetesに変更する 負荷テストの実施 スケール戦略の変更 カナリアリリースの実施 成果 開発速度の向上 運用コストの軽減 レスポンス速度の向上 既存の構成・知識の集約 まとめ 画像変換サーバの特性 弊社ではLIFULL HOME'Sを始め、さまざまなアプリケーションから画像変換サーバを利用しています。 今回移行した画像変換サーバは、nginx用の動的画像モジュールの ngx_small_light を採用した自作のアプリケーションとなっています。 主な役割について簡単に説明すると、呼び出し元のアプリケーションが画像を取得する際に画像変換サーバは画像のサイズと画質を動的に変換し、アプリケーションに返却する役割を担っています。 常に数千RPSを受け取り、繁忙期にはさらに多くのリクエストが増えます。 開発における課題 もともと画像変換サーバを移行するきっかけになったのは私がLIFULL HOME'Sの画像の最適化を行いたいと思ったのがきっかけでした。 ユーザーに対して品質のよい画像を届けたり優れた体験のために読み込み速度を改善したいというモチベーションで改善を行いたいと思っていました。 LIFULL HOME'Sでは物件の内観や外観の画像を始め、ほとんどのページで画像を画像変換サーバから取得しています。 LIFULL HOME'Sのような不動産情報ポータルサイトにおける画像の重要性は非常に高く、画像配信を行うアプリケーションに機能改修を行うことでサイト全体の大幅なパワーアップを行うことができます。 しかしながらそれを実現するにあたりさまざまな課題を感じ、今のまま改修をするのは効率が良くないと思い、開発体験の向上を行う手段を講じることにしました。 開発体験の向上を行うにあたり、システム刷新をするかアプリケーションの新基盤刷新を行うかを天秤に取ったところ、画像変換サーバを利用するアプリケーションが多いことから影響範囲の広さと実装コストなどさまざまな要因から検討を重ねた結果、今回はアプリケーションの新基盤移行を行うことにしました。 課題1: 開発しづらいアプリケーション 既存の画像変換サーバは、アプリケーション開発者にとって改修しづらいアプリケーションになっていました。 その要因は大きく分けて以下の2点です。 運用をしているチームがインフラ開発チームであること アプリケーションの検証環境を気軽に用意できないこと 画像変換サーバは大量のインスタンスにより動作するアプリケーションであり、インフラチームの管轄として運用されていました。 そのためアプリケーション開発者には制限が多く、 検証サーバの作成やデプロイなどにも手間がかかり画像変換サーバを改修することが容易ではありませんでした。 また、開発にはインフラチームに検証環境を用意してもらう必要があり、すぐに検証を行うことができないことも開発速度を遅くしていました。 したがって、開発者が手元のマシンで気軽にアプリケーションを立ち上げるしくみを用意する必要がありました。 課題2: インフラリソースの最適化の余地の向上 画像変換サーバに対して圧縮率の変更やフォーマットのWebP化などの機能改修を行いたいモチベーションがあるのはアプリケーション開発者にあることが多いです。 また、インフラリソースなどの変更に対する権限もアプリケーションの特性を把握しやすいアプリケーション開発者が持つことによるメリットは多いと思います。 しかしながら、現状の組織運用体制ではアプリケーション開発者に検証と調整を気軽に行うことができませんでした。 したがって、アプリケーション開発者に自由にインフラリソースを変更する権限を与えられるようにすることが必要だと考えていました。 また、もともとの画像変換サーバはEC2インスタンスを非常に多く起動させるアプリケーションであることからコスト面での課題を抱えていました。 弊社のアプリケーションのほとんどが画像変換サーバを利用していることから、サーバがダウンしてしまうことに対するリスクは非常に大きいです。 そのため唐突なスパイクリクエストが来ても問題なくアプリケーションが動作できるだけの運用台数を用意する必要がありました。 大きめのEC2インスタンスを数十台で運用し、高コストでの運用が続いていました。 実際にやったこと 上記に挙げた課題を解決するためにやったことをセクションベースで記載していきます。 実際の画像変換サーバを読み解く 画像変換サーバを刷新することを決めたものの、その状況は芳しくないものでした。 というのも古いアプリケーションであり機能改修が少なかったこともあり、実際の運用やアプリケーションについての特性を正しく把握している人が社内に存在していませんでした。 したがって実際のデプロイフローやnginxの内容から何をしているアプリケーションなのかやデプロイに必要な構成要素を洗い出す必要がありました。 まずデプロイ内容やインフラ構成については、既存の画像変換サーバはリポジトリ管理等もされておらず、リリースに必要なものが各所に点在している状況でした。 ですので、当時デプロイ運用で利用されていたAnsible playbookとCloudFormationの内容を読み解き、デプロイに必要な要素を一つ一つ洗い出しつつまとめていきました。 またアプリケーションを理解している人もいない状況でした。 そこで、インフラチームに既存と同一のインスタンスを準備してもらった上で、nginxの内容を読み解きつつ必要なモジュールの確認や挙動の確認を進めました。 コンテナベースに置き換える 大まかな構成要素が洗い出されましたので、アプリケーションを構成し直しました。 もともと課題にあげた通り、開発者が気軽に検証環境を手元に用意できないという課題を解決するために、コンテナ化をすることにしました。 基本的なアプリケーションの構成要素やデプロイに必要なものはAnsible playbook等の内容に記載されていたので、それにしたがってコンテナ化を進めていきました。 そのタイミングで利用しているソフトウェアやBase Imageなども極力アップデートしています。 実行基盤をEC2からKubernetesに変更する 課題2に挙げた通り、アプリケーション開発者がインフラリソースを変更できるようにしたいという希望がありました。 それを実現する具体的なアプローチとして、実行基盤をKubernetesに移行することとしました。 弊社では全社的にインフラ環境をKEELという独自のKubernetesベースのアプリケーション実行基盤に移行していくことになっています。 KEELについてはこちらのエントリに記載されています。 https://www.lifull.blog/entry/2020/12/02/000000 もともとEC2で運用をされていたアプリケーションをKubernetes環境であるKEELに移行することは今回の課題であるアプリケーション開発者がインフラリソースを容易に調整をできることや検証環境を容易に作成できる点に対する明確かつ有効的なアプローチであることからKEELの実行基盤への移行を決定し、既存アプリケーションのコンテナ化を実施したうえで、KEEL環境へデプロイする形にしました。 負荷テストの実施 コンテナ化とKubernetes移行が完成したタイミングで負荷検証を実施しています。 既存の画像変換サーバが大量にリクエストされるアプリケーションであり、さまざまなアプリケーションから使われている都合上、アプリケーションの切り替えには無停止での入れ替えをする必要がありました。 したがって、既存のリクエストがさばけるように長期間にかけて、多種多様のリクエストを想定したシナリオを用意し安定してさばくことができるリソースの調整を行いました。 具体的には以下の手順にで負荷検証を実施しました。 1台のpodがさばける限界のリクエスト量を測定 一台あたりのスループットを確認 1.で求めた最大のリクエスト量の2倍を2台のpodでさばくことができるかを検証 podが増えたことで線形にスループットが増えることを検証 スケールアウトする閾値の検証 今回はcpuに負荷のかかるアプリケーションであったため、2.で実行したリクエスト量を安定してさばける台数とスケールアウトするタイミングを決定 実際に必要なpodの数を検証 3.でもとめたリクエスト量を安定してさばくことができるpodの台数から実際のリクエストを受け取る場合に必要な台数を求めて必要なpodの台数を決定 実際にプロダクトインしたケースを踏まえてsoakテスト(長時間のリクエストテスト)の実施 長時間リクエストを受け続けてもアプリケーションに問題がないことを確認 スケール戦略の変更 今回の移行時にスケールアアップ+スケールアウトの両軸で運用していた画像変換サーバをスケールアウトに寄せる形で運用しなおしました。 Kubernetes環境になったことで大きく変わったことがいくつかありますが、その一つがスケールアウトの時間が大幅に削減したことでした。 具体的な数字を挙げると、既存の画像変換サーバがスケールアウトするのには1分から2分必要だったところKubernetes環境化にすることで、15秒ほどにまで削減することが可能になりました。 それにより、スケールアウトに対する比重を非常に高く持つことができるようになりました。 したがって、サーバ1台に対してリソースの余裕を持たせる割合が少なくなり、サーバ1台あたりのリソースを削減できることができました。 また、既存の画像変換サーバは大きめのインスタンスをある程度準備している状況を常態化させる形にしていました。 したがって、朝方などのリクエストの少ない時間にリソースが余る状況になってしまっていたことも多々ありました。 そこで、一台あたりのリソースを極限に少なくし大量のサーバでさばく戦略に変えることで、リクエストの数に応じたリソース調整を行える形にすることでリソースに対する無駄を排除することにしました。 カナリアリリースの実施 今回の画像変換サーバは数多くのアプリケーションから利用されているアプリケーションであるため、無停止での移行をする必要があったので、それを行う手法としてカナリアリリースを実施しています。 約二週間の期間をかけて徐々に割合を上げていく形で切り替えていきました。 成果 上記に挙げたやったことを実施したことでいくつか成果につながることができましたので紹介します。 開発速度の向上 コンテナ化やKubernetes環境に移行したことで、自前で開発用のサーバを気軽に用意したり検証できるようになったので、今までに比べて格段に開発しやすくなりました。 そのわかりやすい例として、もともと私が基盤移行をする前に画像変換サーバに対して行いたかった改修の一つとして、画像の画質変更をするというものがありました。 内容としてはそこまで工数がかかるものではなかったのですが、既存の画像変換サーバに機能改修をすると他グループの作業にも依存するため検証環境の構築待ちなども発生しおおよそ2週間ほど時間を要してしまうことになるところ、検証まで含めて一日でリリースできるようになりました。 非常に検証が行いやすくなったことやアプリケーション開発者側にデプロイの権限が移ったことにより開発速度の圧倒的な向上を行うことができたのは機能開発に対するコストの兼ね合いからかなり大きな成果でした。 運用コストの軽減 nginxのチューニングやスケールアウト戦略に変更したことで非常にリソースを抑えることに成功しました。 リソースを縮小させた主な要因は以下のようなことが挙げられます。 pod一台あたりのリソースの縮小化 スケールアップ戦略からスケールアウト戦略への変更 一台あたりがさばけるリクエストの数を増加させる その結果、もともと大きめのEC2インスタンスを数十台で運用していたため高コストで運用していた画像変換サーバを約1/3のコストで運用することに成功しました。 レスポンス速度の向上 アプリケーションの構成を入れ替えの実施や、nginx-exporterを導入したうえでworker数の最適化を行うなどの改善をしたことにより、レスポンス速度にも大きな改善が見られました。 具体的な数値としては、平均レスポンスタイムは230msec → 110msecほどまでに短縮でき、アプリケーション全体のパフォーマンスを向上させることにつながっています。 既存の構成・知識の集約 GitHubリポジトリを今回新規に用意し、リリースに必要なものをすべて集約しました。 画像サーバはもともとリポジトリ管理されているアプリケーションではありませんでした。 したがって、アプリケーションの構成に必要なファイルやスクリプトが一ヵ所に集約されておらず、リリースに必要なものがすぐにはわからないという状態でした。 それを今回のタイミングでリポジトリ管理したことにより見るべき場所を単一化できたほか、機能改修のバージョニングを行うことができたので開発者目線で運用しやすいプロダクトになりました。 まとめ 今回はさまざまな要因から開発しづらいアプリケーションだった画像変換サーバを再構築並びに新規実行基盤に移し替えたお話をさせていただきました。 レガシーなシステムであったり、運用体制であったりと開発工数や調査工数が嵩んでしまうことというのはいたってめづらしい話しではないかと思います。 そのような場合にはたいへんだなーで終わらせず現状の課題を洗い出し、エンジニア的アプローチで改善をしてみることで、未来へつながるアプリケーションにできるかもしれません。 今回はその手法として基盤刷新をするというものでしたが、基盤刷新に限った話ではないと思いますので、さまざまなアプローチを視野に入れてアプリケーションの改善してはいかがでしょうか。 最後に、LIFULL ではともに成長していける仲間を募集しています。よろしければこちらのページもご覧ください。 hrmos.co hrmos.co
こんにちは!クリエイターの日運営委員の工藤です。 社内で熱海をフィールドとしたハッカソンを開催しました。 ハッカソンとは、ハックとマラソンを組み合わせた造語で1日から数日でエンジニアやデザイナー、プランナーでサービスのアイデアを考え開発するイベントです。 LIFULLは社会課題の解決を目指している企業であるため、実際に現地の課題を見に行ってサービスを考えるということでより課題に目を向けてサービスの開発ができるようになると考え開催しました。 今回LIFULLが運営しているLivingAnywhere Commons(LAC)が熱海に拠点があるため熱海をフィールドとしてハッカソンを行いました。テーマは「LAC熱海をさらに盛り上げるには」で、このLACの熱海拠点を盛り上げるサービスを各チームに分かれて考え開発しました。 livinganywherecommons.com ハッカソンの流れ 今回のハッカソンは1泊2日で行いました。 熱海に集合してそこからみんなでLAC熱海に移動し、熱海の現状や課題などを聞きました。 その後、チームに分かれて熱海の街のフィールドワークを行いました。実際に熱海の街を歩いたり、LAC熱海のコミュニティマネージャーに質問したり実際にある課題を調べ深堀りしていきました。 各チーム解決したい課題が見えてきたら徐々に開発に移っていきました。この写真のようなLAC熱海の宿泊施設やコワーキングスペースなどで各チームに分かれて開発しています。 成果発表 最後に2日間で開発したサービスの発表を行いました。 各チームが開発したものを簡単に紹介します。 まずはチーム「熱海の空」の「KYOU〜経由地〜」です。 こちらのチームは企画1名、エンジニア3名のチームです このサービスは、LAC周辺にいる利用者とお店の位置を表示することにより、LACユーザーと地元の方々を繋げることを目的としたものです。このアイデアは、LACで配布されている「まちあるきマップ」という地図を使って地元のお店を訪れる際、その地図をきっかけにコミュニケーションが生まれることからインスパイアされています。 続いてチーム「ムシメガネ」の「musubi」です。 こちらのチームは企画1名、デザイナー1名、エンジニア2名のチームです。 このサービスは、LAC熱海にチェックインする際にプロフィールと興味あること、話したいことを登録することで同じくLAC熱海に泊まってるユーザと話す約束ができるサービスです。これは、LAC熱海はコミュニケーションを大事にしているものの建物が3つあるためコミュニケーションが取りにくい課題に注目しました。 さいごに どちらのチームもエンジニアだけでなく、様々な職種でチームが構成されそれそれの得意分野をいかしてサービスの開発を行いました。 実際に課題のある現場を見て、生の声を聞くことでよりユーザのことを考えたサービスの開発ができたと思います。これは普段の業務でもとても重要なことなので今後の業務にもいかせたらと思います。 LIFULLでは今後もこのような社会課題などに向き合ったサービスの開発を続けていきます。 最後に、LIFULL ではともに成長していける仲間を募集しています。よろしければこちらのページもご覧ください。 hrmos.co hrmos.co
はじめまして、テクノロジー本部の布川です。そろそろ入社して一年が過ぎようとしています。 本記事ではLIFULL HOME'Sのページ高速化PJの一環として行われた、マイクロサービス間のhttp keepaliveを自前で有効化する取り組みについてお話しさせていただきます。 同じように高速化を行おうとしている方々の参考になればとても幸いです。 背景と目的 プラットフォームGと高速化について 2021年6月にGoogleがWebサイトの性能指標としてCore Web Vitalsを導入してから、サイトの読み込みや操作に対する応答の速度、レイアウトの安定性といった指標がSEOに影響を与えるようになりました。私の所属するプラットフォームGの高速化チームは、LIFULL HOME'Sの主要なページのパフォーマンスを監視しながら、主にサイトの読み込み速度の改善に取り組んでいます。 サイトの読み込み速度の改善方法は、大きくフロントエンドからのアプローチとバックエンドからのアプローチの二種類に分かれます。特に後者について挙げられる手段は、システムの構成や使われている言語やフレームワークなどのさまざまな条件に左右されるため多岐に渡りますが、どれも「できるだけ早くブラウザにレスポンスを返す」ことに繋がっています。 今回の話は、バックエンドからのアプローチに寄ったものになります。 LIFULLにおけるパフォーマンス改善に向けた取り組み 弊社の提供する不動産ポータルサイトであるLIFULL HOME'Sは、KEELと呼ばれるkubernetesベースのアプリケーション実行基盤の上で連携する複数のコンポーネントによって構成されています。システムを構成する要素が複数ある場合はボトルネックの特定が難しくなるため、横断的なパフォーマンス改善が難しくなってしまう側面がありますが、KEELがLIFULL HOME'Sに向けて提供しているログの横断検索機能やリクエストの分散トレーシング機能を活用することで、効率の良い改善活動を行うことができています。 www.lifull.blog KEELの上ではLIFULL HOME'Sに直接関係するサービスの他にもたくさんのアプリケーションが動いており、その一つ一つにパフォーマンス改善に関わる機能以外にも、自動デプロイフローやサービスメッシュ、セキュリティなど運用上必要になるさまざまなものが提供されています。 ボトルネックの発見 KEELでは、サービスメッシュとして導入しているistioが各マイクロサービスに付加するistio-proxyによって、サービスが通信時に必要とするトラフィックの管理などに関する機能を提供しています。しかしリクエストを直列に処理するモデルの関係上、一部のマイクロサービスではパフォーマンスの観点からistio-proxyの付与を無効にして、直接相手のサーバとやり取りしていることがあります。 LIFULL HOME'Sではフロントサーバの裏でAPIサーバやページ毎のリソースを集約するBFFが動いていますが、現状これらのサーバではistio-proxyが無効化されています。そのためこれらのサーバ間で通信を行う際は、リクエストのたびに接続を張り直したりリトライ処理が正しく行われていなかったりといった問題があり、特に都度接続を張り直すことに関してはサイトの読み込み速度の低下に繋がっていることが考えられました。そこで、httpクライアントの実装やサーバ側の設定を適切に行うことで、istio-proxyの無効化により失われていた機能のうちhttp keepaliveやリトライ機能を自前で有効化することにしました。 課題と対応 マイクロサービス間のhttp keepaliveを自前で有効化する(=リクエスト/レスポンスのConnectionヘッダにkeep-aliveを指定する)にあたり、解決すべき課題がいくつかありました。 内外のコンポーネントへの影響調査 コネクションプールの作成 スケーリング時の対応 その中でも主な課題について、それぞれの詳細と行った対応について説明していきます。 内外のコンポーネントへの影響調査 http keepaliveを有効化するとクライアント-サーバ間で一度張られたtcp接続は一定期間保持されるようになりますが、この時ある時間帯に張られる接続の数は減少するものの、あるタイミングで同時に張られる接続の数は増加します。そのため、サーバが同時管理する接続数が現状からどの程度増え、それが許容できる範囲なのか否かを調査しました。 その結果、APIサーバで一つのpodに対して同時に張られる可能性のある接続の数と比較して、それぞれのpodにいるnginxが管理できる接続数に十分余裕があることを確認しました。 また、APIサーバに直接接続してくる他のサービスのhttpクライアントが、APIサーバ側のhttp keepaliveが有効な場合は接続を使い回すようになるのか、その際接続が切れたら繋ぎ直すなどの必要な処理を正しく行えているのかといった他サービスの調査も念の為行いました。 実際、istio-proxyを無効にしてAPIサーバに直接アクセスしてくるマイクロサービスは他に2つほどあり、それぞれのhttpクライアントはnode(v14), python(v3.7)のものを使っていましたが、以下のように問題がないことを確認しました。 node(v14): デフォルトでkeepalive無効( 参考 ) python(v3.7): デフォルトでkeepalive有効、切断時のハンドリングは正しく行われている( 参考 ) コネクションプールの作成 先ほどの図のようにBFFにおいては一つのpodの中で複数のpassanger worker processが動いており、それぞれのworker processがフロントエンドサーバから受け取った一つのリクエストを処理しています。このworker processがスレッド並列でAPIサーバにリクエストを投げる際に張る接続を、http keepaliveによって一定期間保持して使い回そうとしています。 この時、あるworker processがAPIサーバに対して逐次的なリクエストしか行わないのであれば、worker process毎に保持する接続は一つで事足ります。しかし、worker processがAPIサーバに対してスレッド並列的にリクエストを投げる場合、worker process毎に複数の接続をスレッドセーフな状態で保持する必要があります。 これについては、worker process毎に一つのコネクションプールを保持し、リクエストを投げる際はプール内の使用可能な接続を使い回せるようにすることで解決しました。BFF上で動くアプリケーションはrubyによって記述されていますが、rubyの標準的なhttpクライアントであるnet/httpはコネクションプールの機構を持たないため、新しく Gem を導入して実装を行いました。 スケーリング時の対応 現在のkubernetesの運用では、事前に定義したHorizontal Autoscaling Policyに基づいて15秒毎にスケールするか否かの判断を行います。この時、APIサーバのスケールインによって接続先のホストがいなくなった場合やスケールアウトによって接続可能なホストが増えた場合のハンドリングを、BFF上のアプリケーションで正しく行う必要がありました。 スケールイン: APIサーバ側のpod数が減少するとBFF側で保持しているいくつかの接続では通信相手がいなくなるため、繋ぎ直しを行う必要があります。net/httpはあるtcp接続を使い回すにあたり自分もしくは相手からの終了処理によってソケットが閉じられていた際は次回使用時に自動的に再接続を行うため、この仕様とkubernetesのルーティング機能によってまだ生きているAPIサーバのpodと接続を張り直すことができました。 スケールアウト: APIサーバ側のpod数が増加しても、BFF側で新しく増えたpodに対して一部の接続を張り直すよう能動的に行動を起こすことはできません。また、kubernetesのデフォルトの通信機構ではkube-proxyによってラウンドロビンなリクエストの振り分けが行われているため、そのままでは新しく生成されたpodへの接続数が少なく偏ってしまいます。この問題についてはAPIサーバ側でkeepalive timeoutをスケール頻度である15秒に調整することで、BFFが定期的に接続を張り直せるようにしました。こうすることによって定期的な接続のバランシングが行われ、APIサーバの一つのpodあたりの接続数はほぼ均等に保たれます。 改善の様子 以上の取り組みによってistio-proxyが無効なマイクロサービス間のhttp keepaliveを有効化することができ、以下のように接続の張り直しがリクエストの度に行われなくなりました。 これによって、特に多くのリソースを要求するページにおけるサーバーレスポンスタイムが以下のように改善しました。 上のグラフは開発環境で各条件ごとに調査した結果ですが、本番環境でも同ページのリリース前日とリリース翌日の24時間のサーバーレスポンスタイムの平均を比較すると、34ms程の改善が見られました。程度に差はあれど裏側でリソースを要求するLIFULL HOME'Sの全ページが今回の施策の恩恵を受けることになります。 また、直接的なパフォーマンスの改善の他にも、active connection数の低減などといった効果が見られました。 まとめ マイクロサービス間のhttp keepaliveを自前で有効化する取り組みについて、接続を使い回すことに伴ういろいろな問題に対処しながら実装を行い、パフォーマンスの改善に繋げたお話でした。ここまで読んでいただきありがとうございました。 今回の施策によって生まれた改善は小さいように見えますが、このような小さな改善を積み重ねる過程でノウハウを蓄積させ、次の改善やパフォーマンスの劣化防止に繋げていくことが重要だと感じます。また、タスクの中ではkubernetesがいかに多くのことをやってくれているかや、インフラやミドルウェアに対する理解が高速化の文脈でも重要になってくることを感じました。 社内の様々な人に助けてもらいながらリリースに漕ぎ着けたこちらのタスクですが、今後は今回の経験と反省をもとに更なるパフォーマンス改善に取り組みSEOに強く良い体験のできるサイトに近付けて行ければと思います。 最後に、LIFULLでは共に成長できるような仲間を募っています。よろしければこちらのページもご覧ください。 hrmos.co hrmos.co
フロントエンドエンジニアの嶌田です。株式会社 LIFULL でプロダクトのアクセシビリティ向上をミッションとして活動しています。 本日は、不動産・住宅情報の総合サービスである LIFULL HOME'S のスマートフォンサイト において、過去半年間で実施したアクセシビリティ向上施策をご紹介します。ご紹介する施策のうちいくつかは、内容を掘り下げて実装コードを交えて解説をしていきます。 それでは、早速アクセシビリティ向上のために実施した施策を見ていきましょう。 ボタンを正しくボタンにする 追加コンテンツを読み込む機能のフォーカス管理 チェックボックスに適切な名前を付ける カルーセルをアクセシブルにする スクリーンリーダーによる検索結果の件数の読み上げ そのほかの改善点 おわりに ボタンを正しくボタンにする ウェブサイトにおいて、ユーザーがアクションを実行するためにボタンが用いられます。ボタンは通常 button 要素を使って実装するのが望ましいですが、適切ではない要素(例えば a 要素、 span 要素、 p 要素など)を使って実装された箇所が数多くありました。これでは キーボード操作ができず、スクリーンリーダーにも「ボタン」であることが伝わりません 。そこで、私たちはこれらの要素を正しくボタンにし、キーボード操作が可能になるよう改善を行いました。 p 要素、 dt 要素、 a 要素、 span 要素など、様々な要素で実装されたボタンたち button 要素に差し替えるのが王道です。とはいえ、 button 要素がデフォルトで持っているスタイルのリセットや、要素セレクタに依存した JS の処理の存在を考慮すると、要素の書き換えによって予期しない不具合を呼び込んでしまうかもしれません。ノーリスクかつ最小工数を目指したかった私たちは、WAI-ARIA を使って役割を上書きすることにしました。 次のような HTML があったとします。 < p class = "load-more" > もっと見る </ p > p 要素はデフォルトで paragraph の役割を持っています 1 。ボタンではありません。ボタンであることを示すために、 role 属性を使って役割を上書きします。 < p class = "load-more" role = "button" > もっと見る </ p > 次に、キーボードで操作できるようにします。このボタンはマウスクリックで機能が実行されるようになっていますが、キーボードフォーカスが当たらないためキーボードのみで操作できません。 tabindex="0" を設定すると、通常のインタラクティブ要素( a 要素やフォーム関連要素など)のようにフォーカスを受取るようになります。 < p class = "load-more" role = "button" tabindex = "0" > もっと見る </ p > これで問題が解決したと思いきや、キーボード操作を試すと、元々の機能が実行されないことに気付きます。 button 要素や a 要素でないと、Enter キーや Space キーが押されたときに click イベントが発火しないことが原因です。JavaScript を使ってここの穴を埋めてあげましょう。コード例 2 は Stimulus です。 < p class = "load-more" role = "button" tabindex = "0" data -controller= "button" data - action = "keydown->button#keyboardClick" > もっと見る </ p > // button_controller.js import { Controller } from '@hotwired/stimulus' ; export default class extends Controller { keyboardClick( event ) { if ( [ 'Enter' , ' ' ] .includes( event .key)) { event .preventDefault(); event .stopPropagation(); this .element.click(); } } } 以上の対応により、p 要素がボタンとしての意味と振る舞いを持つようになりました。さらに、HTML の構造が変わらないため、スタイルの調整は不要であり、既存のイベントハンドラを修正する必要もありません。 追加コンテンツを読み込む機能のフォーカス管理 LIFULL HOME'S では、クリックにより追加コンテンツが表示される UI パターンがよく使われています。このパターンでは、ボタンをクリックするとボタンが消え、追加コンテンツが表示されます。このボタンが消える特徴は、ディスクロージャー 3 と呼ばれる UI パターンとはやや異なります。 ボタンをクリックするとボタンは消え、代わりに追加のコンテンツが表示される この部分にアクセシビリティ上の問題がありました。 ボタンを押すと同時にボタンが消え、同時にキーボードフォーカスが失われてしまう のです。フォーカスの位置がわからなくなり、キーボード操作を行うユーザーにとって不便な状況が生じます。この問題を解決するために、 ボタンをクリックしたときに表示されるコンテンツにフォーカスを当てる ように改善を行いました。 次の HTML コードを想定します。追加で読み込まれるコンテンツには hidden クラスが付いています。CSS で .hidden { display: none } が指定されていると想定してください。 < div > < a href = "..." > 敷金礼金0(ゼロ・なし)の物件 </ a > < a href = "..." > 新築・築浅物件 </ a > </ div > < button class = "load-more" type = "button" > もっと見る </ button > < div class = "hidden" > < a href = "..." > 二人暮らし物件 </ a > < a href = "..." > タワーマンション(高層マンション) </ a > </ div > 追加コンテンツの表示には hidden クラスを取り除き、ボタンを非表示にするには hidden クラスを付与します。 キーボード操作の場合、元々フォーカスがあったボタンが消えてしまいます。そこで、追加で表示されるコンテンツにフォーカスを移動してあげることで、キーボード操作のユーザーが操作箇所を見失わないようにします。 これらの観点を実装すると以下のようになります。まず HTML に、 aria-controls 属性を使って、ボタンの操作対象となる要素を関連付けます 4 。 < div > < a href = "..." > 敷金礼金0(ゼロ・なし)の物件 </ a > < a href = "..." > 新築・築浅物件 </ a > </ div > < button class = "load-more" type = "button" aria-controls = "next-content" data -controller= "inlay" data - action = "inlay#show" > もっと見る </ button > < div id = "next-content" class = "hidden" > < a href = "..." > 二人暮らし物件 </ a > < a href = "..." > タワーマンション(高層マンション) </ a > </ div > JavaScript のコードは次のようになります。ボタンをクリックすると show メソッドが呼ばれます。やや複雑ですが、 追加で表示される最初のタブ可能な要素にフォーカスを当てる という処理が読み取れるでしょうか? また、コード内で使用されている tabbable 関数は、パラメーターに渡された要素内の「タブ可能な」要素を列挙し、配列として返す npm パッケージです 5 。 // inlay_controller.js import { Controller } from '@hotwired/stimulus' ; import { tabbable } from 'tabbable' ; export default class extends Controller { show() { this .nextContent.classList.remove( 'hidden' ); this .element.classList.add( 'hidden' ); this .firstTabbableItem?.focus(); } get nextContent() { let control = this .element.getAttribute( 'aria-controls' ); return document .getElementById(control); } get firstTabbableItem() { return tabbable( this .nextContent) [ 0 ] ; } } チェックボックスに適切な名前を付ける 物件の一覧ページでは、物件を複数選び、まとめて不動産屋に問い合わせたり、お気に入りに追加したりできる機能が提供されています。そのために各物件にはチェックボックスが設けられています。しかし、このチェックボックスには適切な名前が設定されておらず、スクリーンリーダーで利用するときに「クリック可能 チェックボックス チェックなし」としか読み上げられず、 何のチェックボックスなのかわからない 状況が発生しています。 スクリーンリーダーでチェックボックスにフォーカスを当てると「クリック可能 チェックボックス チェックなし」と読み上げられる HTML を見ると、チェックボックスが単体で置かれているだけで、ラベルと紐づいていないことがわかります。 < div class = "room" > < input type = "checkbox" > < div class = "spec" > < p class = "photo noImage" > No Image </ p > < p class = "spec" > -/3LDK/120.00m² 8.5万円 管理費:12,000円 敷金1ヶ月/礼金1ヶ月 </ p > </ div > </ div > この問題を解決する難しさは、チェックボックスが建物全体ではなく各部屋を対象としているため、簡潔で明確なラベルが存在しないことです。適切な名前を設定するためには、適切な場所を探し出し、それを名前として使用する必要があります。 解決策として、 部屋の間取り・面積・賃料などを表すテキスト部分をラベルとして使用 しました。チェックボックスとラベルは離れた場所にあるため、 label 要素の for 属性を使うか、チェックボックスに aria-labelledby 属性をつけることで名前を指定します。今回は事情 6 があって、 aria-labelledby を用いました。 < div class = "room" > < input type = "checkbox" aria-labelledby = "room-0123" > < div class = "spec" > < p class = "photo noImage" > No Image </ p > < p id = "room-0123" class = "spec" > -/3LDK/120.00m² 8.5万円 管理費:12,000円 敷金1ヶ月/礼金1ヶ月 </ p > </ div > </ div > この対応により、スクリーンリーダーによる読み上げは「クリック可能 -/3LDK/120.00m² 8.5万円 管理費:12,000円 敷金 1ヶ月/ 礼金 1ヶ月 チェックボックス チェックなし」となりました。正直なところ、この読み上げ方で完全に不便なく利用できるかは疑問が残りますが、何もない状態よりは改善されているでしょう。 カルーセルをアクセシブルにする カルーセルはアクセシビリティ上の問題が起きやすい UI です。スライダーなどとも呼ばれたりします。LIFULL HOME'S のトップページにもドドンとカルーセルが置かれています。カルーセルに起因する問題はいろいろとありますが、中でも致命的な問題につながるのは「自動再生」です。一定時間ごとにスライドが切り替わる機能です。 3秒ごとにスライドが切り替わるカルーセル LIFULL HOME'S のカルーセルも自動再生つきのものでした。自動再生するカルーセルは WCAG の達成基準「 2.2.2 一時停止、停止、非表示 」に違反しており、 動きのあるコンテンツの動きを追うのが苦手な人や、切り替わるスピードに合わせて文字を読み切れない人は利用が難しいでしょう。動きに気を取られて注意が維持できなくなる人は、ページのほかの部分が利用できなくなることすらあり得ます。 代表的な解決策は「一時停止ボタンを設ける」というものです。自動再生はするものの、一時停止ボタンを押せば動きは止まるため、自分のペースでスライドを見ていけるようになります。 今回、私たちは「 自動再生せず、アクセスごとにスライドをランダムに並び替える 」というアプローチをとりました。自動再生を導入するモチベーションは、複数の優先度の高いコンテンツをユーザーに提示することです。ランダムに並び替えて表示することでも同様の結果は得られるだろうと考えました。 自動再生されなくなったカルーセル うれしかった副次的効果として、もともと後ろのほうに追いやられていたスライドのクリック率が向上しました。カルーセルのスライドは、最初に表示されるスライドの優先度が高いという「大まかな」傾向はある一方、後のほうのスライドの優先度が低いとは必ずしも言えません。スライドをランダムに並び替えると、これまで埋もれていたスライドがユーザーに届くようになる可能性もあり、ランダム化は意外と多くのユースケースで有効な手法かもしれないと思いました。 ちなみに、スライドを前後に送るボタンもコントラストを高くし、視認性が向上しています。 スクリーンリーダーによる検索結果の件数の読み上げ LIFULL HOME'S では、物件を探す際に検索条件を指定することができます。現在の条件で検索した場合のヒット件数が、画面下部にリアルタイムで表示されます。 検索条件を変更すると、該当物件の件数がリアルタイムに更新される スクリーンリーダーの利用者は、このような 操作と離れた場所で変化が起こったことに気づくことができません 。件数を知るためには、フォームを送信して物件一覧ページまで遷移するか、検索条件の最下部にあるボタンの横まで読み進めなければなりません。 これを解決するために、 該当物件件数の部分をライブリージョンとしてマークアップする ことで、件数の変化がスクリーンリーダーで読み上げられるようになります。 <!-- これまで:変化がスクリーンリーダーで読み上げられない --> < p class = "itemTxt" > 該当物件 < br > < span class = "num" > 1,366 </ span > 件 </ p > <!-- 修正後:変化がスクリーンリーダーで読み上げられる --> < p class = "itemTxt" role = "status" > 該当物件 < br > < span class = "num" > 1,366 </ span > 件 </ p > role="status" という属性が追加されています。この属性によって物件数の部分が「ライブリージョン」となり、内容の変化は逐次スクリーンリーダーによって読み上げられるようになります。類似の属性として role="alert" もあり、こちらはより緊急度の高いフィードバックのために用います 7 。 さて、件数の表示はもう少しだけ複雑な仕様がありました。検索条件が変更されたあと、件数の表示が即座に行われるわけではないという点です。設定された条件の該当物件数がいくつあるかサーバーに問い合わせを行いますが、その間は件数の表示が「…」に変わるのです。 この表示になっている間はスクリーンリーダーで読み上げさせないようにしたいです。そこで、読み込みが行われている間は aria-busy 属性を true に設定することで、読み込み中はテキスト読み上げが行われないようにしました。 < p class = "itemTxt" role = "status" aria-busy = "true" > 該当物件 < br > < span class = "num" > ... </ span > 件 </ p > 以上の対応で、スクリーンリーダーを使用しているユーザーも、該当物件数を確認しながら、自由に検索条件を調整できるようになりました。 そのほかの改善点 さらに、事前に実施していたテストによって明らかになった多くの問題点も修正しています。 名前の付いていないボタンに名前を設定する 名前がなかったボタンに適切な名前を設定しました。スクリーンリーダー利用者もボタンの機能を理解しやすくなりました。 モーダルダイアログのフォーカス管理、キーボード操作対応 キーボード操作だけでモーダルダイアログを利用できるようになりました。 ピンチアウトでズームできるようにする これまでスマートフォンサイトはビューポートの設定( user-scalable=no )によってピンチアウトでのズームが制限されていましたが、この制約を解除しました。 アイコンやテキストのコントラスト改善 一部のアイコンやテキストのコントラストが不足していたため、十分なコントラストが得られるように色を調整しました 8 。 おわりに 本記事では、ウェブアクセシビリティ向上に向けた取り組みとして、いくつかの改善策について解説しました。解説した内容は多くのウェブサイトやサービスで共通するものだと思います。この内容を参考に、ぜひあなたのプロダクトのアクセシビリティ改善に役立ててください。 また、キーボードや支援技術ユーザーの皆さんには是非サイトを使ってみていただき、感想をお聞かせください。ご意見をもとに、さらにアクセスしやすいウェブサイトにしていきたい気持ちです! ここ半年くらいをかけて、LIFULL HOME'S のスマートフォンサイトのアクセシビリティを改善してきました。デスクトップサイトは次の半年で改善を加えていく予定です。テスクトップサイトは特に歴史が長く、コアなファンも多いと聞きます。これからも、一人でも多くのユーザーが快適にサービスを利用できるように品質向上に努めてまいります。 お読みいただきありがとうございました。LIFULL では共に働く仲間を募集しています! hrmos.co hrmos.co ARIA in HTML 日本語訳 (momdo.github.io) ↩ HEY のプロダクションコードから拝借したものです。 参考 ↩ ソシオメディア | ディスクロージャー (sociomedia.co.jp) ↩ aria-controls 属性である必要は必ずしもありません。操作対象の要素を特定できる仕組みとして data 属性を用いてもいいでしょう。 ↩ tabbable - npm (npmjs.com) ↩ 部屋のスペック部分が ul 要素でマークアップされていたため、 label 要素で括ることができなかったことが理由です。 ↩ role="alert" は role="status" よりも高い緊急度を持つ領域のマークアップに向いています。 role="status" の領域での変化は適度なタイミングで読み上げられる一方、 role="alert" は即座に読み上げられることが期待されます。 ↩ LIFULL のブランドカラー #ED6103 は白色 #FFFFFF と組み合わせて用いられますが、この2色間のコントラストはテキストに対して不足(3.32:1)しています。社内的には APCA のコントラスト計算方式を推奨しており、問題ない(59.7)としています。 ↩
プロダクトエンジニアリング部の千葉です。 2022年に新卒で入社して、 売却査定領域 の開発に携わっています。 この記事では、2022年10月から取り組んでいる売却査定CRO(Conversion Rate Optimization)チームの施策について紹介していきます。 CROチーム取り組み紹介 ABテスト施策実施の背景 直面した壁 高速に回るPDCA よかったこと 大変だったこと ユーザーファーストGとの連携 エラーメッセージの見せ方改善の施策化 まとめ CROチーム取り組み紹介 売却査定CROチームでは主に集客用のランディングページ、マンションの売却を検討する人のための棟情報ページなどの最適化のためにABテストの施策を行っています。 2023年3月末までに目指すCVRを定め、その目標達成のために複数のABテスト施策を実施→A寄せまたはB寄せ→改善→新たなABテスト施策の実施といったPDCAを回しています。 ABテスト施策実施の背景 集客用のランディングページは事業インパクトが大きいのですが、直帰率・離脱率が高く改善幅も大きいという課題を抱えていました。そのため、これらのページでチャット式の入力フォームを導入するという施策を実施することになりました。 直面した壁 しかし、一部の媒体ではポリシー違反の懸念があることがわかりました。その結果、集客用の一部のランディングページにのみ、既存の入力フォームとは大きく変わったチャット式の入力フォームが導入されることになりました。 ほかのページでは 既存の入力フォームをより簡潔にしてボタン一つで次ページに遷移できるようにする ファーストビューの印象を変えるために背景色を調整する といったABテスト施策を実施することになりました。 高速に回るPDCA よかったこと 2022年10月からのチーム制の導入によりCRO施策に専念することになりました。 そのため、企画の方のABテスト範囲拡大・縮小や寄せの判断から技術側の開発→リリースまでの時間が短縮され、高速にPDCAを回すことができ、6ヶ月という短い期間の中でも多くの施策を打つことができました。 週1回の定例などでチームでの認識が取れていたことによって、テスト結果のジャッジから次のアクションへ高速に移ることができたことが大きな要因だと思います。 また、CRO施策に専念することにより培われたノウハウを活かすことで、速い開発スピードの中でも不具合をだすことなく進めることができました。 大変だったこと 高速にPDCAが回ることで多くの施策が打てる一方で、大変になるのはB本実装です。 ABテスト施策の実装時には既存のものをAとして新規にBのものが作られます。 ABテストを実施しAパターンに戻ることになった場合には、ABテスト実装分をリバート(差し戻し)すればよいのですが、Bパターンになることになった場合には ABテスト関連のために実装した設定ファイル、効果測定用の処理を全て撤去しなければいけない ABテスト用の設定ファイルでテスト対象を絞り込んでいた場合には、その設定を考慮してロジックを実装しなければいけない ABテストを実施した内容のうち、一部の内容だけを本実装する場合に、本実装の要不要の判断が難しい といった工数がかかってしまいます。 そのため、ABテストの実施の際には高速に開発を行うことができますが、B本実装になると工数がかかってしまい大変でした。 今後は、 ABテスト時にB本実装を見据えた設定ファイルに依存しすぎない実装 ブランチを分けてABテスト実装箇所のみをわかりやすくする などといった改善をしていきたいと考えています。 ユーザーファーストGとの連携 ユーザーファーストGの方に協力していただき、ABテストを実施しているページの課題点・懸念点などを洗い出していただきました。目的としては以下の2つです。 今後の修正対応の方向性を検討する際の判断材料にする ユーザビリティ観点での優位性/深刻度の高い箇所の把握 開発している中で見慣れてしまい見落としてしまっているような部分を、第三者目線からご指摘いただくことで、新たな改善点に気がつくことも多かったです。 エラーメッセージの見せ方改善の施策化 施策の一部として、私自身がかねてから改善したいと思っていた、エラーフォームメッセージの見せ方の改善を施策化することもできました。 所属しているウェブアクセシビリティ推進WGの活動を通して深めた知見から、入力フォームのエラーメッセージと背景の明度差が近く、エラーメッセージが見づらいことに気がつきました。そのことから、利用者にとってエラーの箇所の特定が困難になっている可能性があることを提示し、実際にエラーメッセージを見やすくする修正を行い、リリースすることができました。 エラーメッセージ(before) エラーメッセージ(after) まとめ 売却査定CRO(Conversion Rate Optimization)チームの取り組みについて紹介しました。 売却査定では2022年10月から始まったチーム制ですが、この短期間の中でも多くの施策を打つことができ、よかった点も改善点も含めていろいろな結果をだすことができました。 最後に、LIFULLではともに成長できるような仲間を募っています。 よろしければこちらのページもご覧ください。 hrmos.co hrmos.co
テクノロジー本部の yoshikawa です。 普段の業務では全社データ基盤の開発や技術検証、ビジネスサイドのデータ活用支援を行っています。 本記事では、Google CloudのDataplex(主にData CatalogとData Lineage)を活用したデータマネジメント及びその支援に関する事例を紹介します。 また関連して、データ開発の質とスピードを高めるべくCloud Composerとdbt(dbt Core)を採用し、DWH(データウェアハウス)/DM(データマート)構築基盤を刷新する取り組みについても紹介します。 全社データ基盤の概観 全社データ基盤ができるまで、そしてこれから データマネジメントの必要性 データマネジメントの領域 データマネジメントをエンジニアとして支援する データスチュワードの発足 Dataplexの活用 データのカタログ化と用語集 データリネージの活用 DWH/DM構築基盤の刷新 まとめ 全社データ基盤の概観 LIFULLの全社データ基盤はBigQuery(Google Cloud)を中心としつつETL処理にStep Functions(AWS)などを利用し構成されています。 全社データ基盤には基幹サービスであるLIFULL HOME'S上のログデータや地理情報マスターデータなどのデータソース、それらを事業・用途別に集計・加工したDWH(データウェアハウス)/DM(データマート)など、様々な出自・用途のデータが集約されています。 記事執筆時点での規模は容量にして数百TB、テーブル数にして1万以上と大量のデータが蓄積されており、今もなおデータ量が増加しています。 そうした大量のデータはBI経由で各部署・プロジェクトの指標として定期的に参照されたり、施策の効果測定や検証などアドホック分析、機械学習などに活用されています。 全社データ基盤ができるまで、そしてこれから 数年前、今の全社データ基盤が構築される前はデータ活用に関して下記のような課題がありました。 クラウドサービスやDBにデータが散在(サイロ化)している セキュリティの観点からデータを抽出可能な人が限定されている データを使う人(アナリスト、企画、etc)と、データを抽出できる人(エンジニア)が別なので、手戻りが頻発しデータを使うまでの効率が悪い そうした課題を解決すべく今の全社データ基盤が構築され、BigQueryへのデータ集約やIAMによる権限管理によって課題は解決されてきました。 (全社データ基盤が構築されるまでの沿革は過去のブログからご覧になれます。) www.lifull.blog 利用実績の増加を遂げつつデータを蓄積し続けている全社データ基盤ですが、これからはデータを蓄積し誰でも利用できるようにするだけでなく、データの活用を通じ価値提供を促すことで、利益という形でも貢献できる基盤へと成長していくことが重要となります。 データマネジメントの必要性 現在、全社データ基盤が安定稼働している中でデータ活用に関して下記のような課題があります。 データを利活用するステークホルダーの増加・多様化、およびそれに伴う要望の複雑化・多様化(人の問題) データを生成する/参照するシステムの増加・複雑化、およびそれに伴う全体統制の難化(システムの問題) データ量の増加・管理の複雑化に伴うデータ品質維持の問題(データの問題) 全社データ基盤が構築される前と比べると業務プロセスの一部分としてデータを活用する際の問題だけではなく、データを扱う人や組織のリテラシーやガバナンス、中長期的にデータ活用を継続していく上での品質の維持や管理コストに関する課題が顕在化しています。 そのため、システムの一つとしてデータ基盤を開発し発展させるだけでなく、人・組織の問題へと越境することで上手くデータ活用をし続ける取り組み→データマネジメントが今の全社データ基盤で必要とされています。 データマネジメントの領域 データマネジメントには多様な領域が存在するとされています。 データマネジメントの知識体系をまとめた書籍として『DMBOK』が有名ですが、データガバナンスを中心とした「DAMAホイール図」と呼ばれる図にデータマネジメントに関する知識領域が定義されています。 (詳細は書籍かデータマネジメント協会 日本支部のホームページをご覧ください) www.dama-japan.org 全社データ基盤においても、データセキュリティやドキュメントとコンテンツ管理、メタデータ(カタログ化)をはじめとした領域でデータマネジメントの取り組みが行われています。 それらの取り組みについて以降で紹介していきます。 データマネジメントをエンジニアとして支援する データマネジメントはデータの生成や基盤に携わるデータエンジニアだけではなく、CDOやデータ基盤・統括に関連するマネージャー、データを活用するアナリストやデータサイエンティストなど多様なステークホルダーと連携し進めていきます。 筆者はデータマネジメントに必要とされる技術(Google Cloudのサービスが中心)についての検証や、ビジネス職(データスチュワード)への技術的な支援・提案といった形で携わっています。 データスチュワードの発足 先の課題として述べたようにステークホルダーの増加や多様化により、データエンジニアだけでデータに関する要望に応えることが難しくなりつつあります。 そこでLIFULLでは昨年末からデータ整備やデータ活用に関する相談窓口を担う役割としてデータスチュワードが発足しています。 Dataplexの活用 冒頭でお伝えしたように、全社データ基盤はGoogle CloudとAWS両方を利用して構成されています。 データ利用者にとって中心となるのはBigQueryであるため、データに関する情報(メタデータ、データ品質、セキュリティレベル、etc)はGoogle Cloudに集約するという流れになりつつあります。 データマネジメントの文脈において重要となるサービスはDataplexです。 cloud.google.com DataplexにはLake、Zone、Assetという論理的な概念を使い、各ストレージ(データレイク、DWH、DM)上のデータをドメイン別に一元的に管理できる機能をはじめ、カタログ機能(これまでのData Catalog)や、データリネージ機能など、データガバナンスおよびデータマネジメントの観点で有用な機能が存在しています。 多様な機能が存在していますが、中長期的なデータマネジメントに貢献するか、および現在のデータスチュワードのユースケースに貢献するかを念頭にいくつかの機能を利用しています。 データのカタログ化と用語集 昨年の夏からデータカタログを利用し始め、現在ではデータスチュワードによるカタログ化(=タグ付けやドキュメンテーション)が進行しています。 中長期的な目標として全てのデータに対してのカタログ化を視野に入れていますが、現在は新規作成されたデータや戦略上重要とされるデータを優先的にカタログ化しています。 カタログ化において注目している機能は用語集(Dataplex business glossaries)です。(記事執筆時点ではpreview版です) cloud.google.com 利用イメージは下記のGoogle Cloud Blogをご覧いただけると良いかと思います。 cloud.google.com 文字通り、事業/ビジネスに関する用語集を作成できる機能ですが、タグテンプレートのようにデータと関連づけを行うこともできます。 全社データ基盤では、Dataplex business glossariesが利用可能になる前からドメイン知識などのビジネス用語とデータとの関連づけを構想していました。 当時はタグテンプレートでの実現を予定していましたが、Dataplex business glossarieはタグテンプレートと比べ以下の点で利点があり、データ整備実施者とデータ利用者の両方にとってメリットがあると考えています。 データに対する用語の関連付けや、用語間の関連付けがGUI上で容易に行える=整備が楽 Data Catalogの検索結果上のスキーマタブで、内容を簡単に把握できる(下図を参照)=欲しい情報が見つけやすい カラムに関連付けられた用語(Business Terms).タグ(Column Tags)はクリックして内容を確認できる一方、用語なら内容が一目でわかる まだpreview段階の機能ではありますが、データソース(BigQuery)と近いところにデータの仕様(Dataplex business glossaries)を蓄積させ、データ利活用者およびデータスチュワードの認知負荷を軽減し、データ利活用の体験を向上させていければ理想的だと考えています。 データリネージの活用 筆者は昨年夏のデータカタログの利用開始と同時期にデータリネージの実現についても検証しています。 その結果として、Audit LogsとINFORMATION_SCHEMAから取得可能なテーブル定義とジョブ実行情報を元データとし、Streamlitとpyvisを用いて可視化するデータリネージアプリを実装しました。 詳細は過去のブログよりご覧いただけます。 www.lifull.blog データリネージアプリは半年程度運用し、その間に下記のようなユースケースが生まれました。 施策によるデータソース定義変更の影響範囲調査 不要データセット削除による影響範囲調査 そんな中、Google Cloudから公式のデータリネージ機能がアナウンスされ利用できるようになりました。(記事執筆時点ではpreview版の機能を含みます) cloud.google.com 機能の詳細は上記公式ドキュメントの通りですが、使用感としてはこれまでに生じた影響範囲というユースケースに対しては対応できると考えており、BigQueryのタブからもアクセスできることから、アドホックな分析でSQLを書きながら関連するデータがないか探索するといった用途にも適していそうです。 記事執筆時点では機能面の充足や費用面への影響を中心に検証を行っており、本番環境への適用に向けて準備をしています。 カスタマイズ性という観点では、自前で容易したデータリネージアプリが勝る場面もありそうですが、先のDataplex business glossariesとあわせ、データに関する情報をGoogle Cloudへと集約することでSSoT(Single Source of Truth)を構築できる良い機会と考えています。 DWH/DM構築基盤の刷新 こちらはデータマネジメントというよりエンジニアリング寄りの内容ですが、5年以上にわたって稼働しているDWH/DM構築基盤の刷新も進行しています。 現状のETL処理基盤はデータパイプライン構築にLuigi、ワークフロー実行環境にStep Functions(AWS)などを採用して構成されています。 現行の全社データ基盤の構成図 当時からデータエンジニアリングに関するツールや知見は進化し、開発速度や開発者体験を向上させる仕組みが整ってきたことから、現行の構成からワークフローの実行および管理の基盤としてCloud Composer、SQL開発およびデータモデリング用にdbt(dbt Core)を採用した基盤へのリプレイスの検証が開始しました。 cloud.google.com www.getdbt.com その他の採用技術の候補としてArgo Workflows(on GKE)やDataformも検討しましたが、 マネージドサービスの恩恵を受けながらも、開発者体験を上げつつデータ開発を効率化できるようComposerとdbtという組み合わせを採用しました。 記事執筆時点では一部処理での検証を実施している段階ですが、下記のようなメリットを感じています。 SQLとワークフロー実行設定が分離されるようになり、SQLにデータ・テーブルに関する仕様が集約されるようになった dbtがSQLの依存関係を解析してくれるため、SQL実行順序の制御が手軽になった スキーマ定義やワークフロー実行制御において手動実行していた開発フローが自動化された まとめ LIFULLの全社データ基盤ではGoogle Cloudを活用しデータマネジメントおよびその支援を進めています。 本記事ではその中でもデータカタログ(Dataplex business glossaries)を利用したカタログ化、データリネージ機能を採用した影響範囲調査の負荷軽減、開発者体験・開発速度の向上を目的とした既存ETL処理基盤の刷新についてお伝えしました。 本記事では紹介しきれなかったデータマネジメントに関連する取り組み(データ品質、データセキュリティなど)も多くあるため、後続のクリエイターズブログでお伝えできればと思います。 最後に、LIFULLではエンジニアを募集しています。カジュアル面談のご応募や現在募集中の職種については下記をご覧ください。 hrmos.co hrmos.co
初めまして! 2022年4月に入社しました、AI戦略室の岩﨑悠紀と申します。 普段の業務では主に機械学習モデルの性能改善を担当しています。 昨今ではChatGPTをはじめとした機械学習プロダクトが世に出始めており、 翻訳やチャットボットなどの自然言語処理、そして画像生成や物体検知などの画像処理の分野が注目を浴びています。 機械学習は応用範囲がとても広く、LIFULLでは間取りの3D画像の生成する「 LIFULL HOME'S 3D間取り 」や、対話型の物件検索システムである「 AIホームズくんBETA 」、一覧画面内の物件の並び替えを行う「AIおすすめ順」などにも利用しています。 その中でも、私は「AIおすすめ順」の機械学習モデル開発・改善に関わっており、この記事ではその取り組みについて紹介したいと思います。 AIおすすめ順 性能改善の事例 解決したかった課題 改善方法 まとめ AIおすすめ順 まずはAIおすすめ順について説明していきます。 AIおすすめ順は、LIFULL HOME'Sの一覧画面内の物件の並び順を機械学習を用いて最適化するプロジェクトで、ユーザーの方々が より魅力的に感じる物件を上位に表示する ことを目的としています。 具体的には、下の図のように機械学習モデルを用いて物件のスペックから「 おすすめスコア 」を算出し、そのスコアに沿って一覧画面内の物件を並び替えています。(図中央は"物件A"に対して機械学習モデルを用いた推論を行っている様子を表していますが、実際には図左側のすべての物件に対して推論を行います。) また、AIおすすめ順の機械学習モデル部分は「ランキング学習」と呼ばれる手法を用いて学習を行い、与えられた物件群の中で人気の物件をより上位に並べ替えるように最適化されています。 具体的には、下の図のようにユーザの方々から人気の物件により高い「おすすめスコア」を付与するように学習を行います。 私の業務はこのAIおすすめ順の機械学習モデルの性能改善で、ユーザーへ魅力的な物件をより高い精度で届けることにつながります。 では、実際にサービスに組み込まれた機械学習モデルの改善事例について紹介したいと思います。 性能改善の事例 解決したかった課題 初期のAIおすすめ順の機械学習モデルでは一年を通して同じ構造のモデルを使用しているため、「◯月はこういう物件がおすすめ!」というように時期によって並び順を変更することができませんでした。 しかし、時期によってユーザーの方々に人気な物件スペックは変化するため、より高い精度でおすすめする物件を届けるためには、 時期ごとに並び替えのロジックを変化させる 必要があります。 改善方法 AIおすすめ順のチームでは上記の課題を解決するために、機械学習モデルの学習時に「その物件がいつ掲載されていたか」という情報を同時に与える実験を行いました。 実験では木構造の機械学習モデルを使用したため、下の図のようにモデル内に分岐が作成されています。 そのため、学習時に掲載時期の情報を与えることにより、「◯月は〜〜の傾向があるから、△△というロジックを使う」というように、 モデル内部で自動的に「その時期に最適なロジック」に切り替える ことができます。 上記の改善を行った結果、オンライン検証(A/Bテスト)で既存のモデルよりも良い結果を得ることができました。 まとめ AIおすすめ順プロジェクトでは、こういった機械学習モデルの性能改善を日々行っています。 これからもユーザーの方々へより魅力的な物件を届けられるように、試行錯誤しながら頑張っていこうと思います。 最後に、LIFULLではともに成長できるような仲間を募っています。 よろしければこちらのページもご覧ください。 hrmos.co hrmos.co
AI戦略室の神谷と申します。データサイエンティストとして、機械学習や数値モデルのアルゴリズム開発に従事しています。最近ではAIをはじめとしたさまざまなデータの活用やビジネスへの応用について興味を持っています。 私が所属するAI戦略室では、将来的な競合他社との差別化を見据えた「AI技術シーズの創出」と短中期的な事業貢献につながる「AI技術シーズの活用」の2本柱となるミッションを持っており、AIとビジネスの橋渡しをどのように行っていくかを日々議論・検討しています(参考: 社内でAI成果展示会を開催しました - LIFULL Creators Blog )。2022年ごろから組織内の特命チームとして、特にAI技術シーズの活用を社内に促進する「AI活用促進チーム」が構成され、日々の業務と並行して社内のAI活用促進を図る業務を担当することになりました。 今回はLIFULLにおけるAI技術の活用という観点から、AIの活用促進の重要性とAI活用促進チームの実際の取り組みについて紹介いたします。 キーワード: AI-Ready化とは AI活用促進の重要なキーワードとして、AI-Ready化というワードがあります。AI-Ready化とは、経団連が企業・個人・制度などあらゆるレイヤーに対するAI活用戦略の指針として定めたもので、「(社会・産業・企業が)AIを活用するための準備」が進んでいる状態を指します。 そもそもの技術背景としてAIによる識別・予測など一部の領域で人間を上回るような事例が増えており、AIシステムが新たなビジネスモデルの構築に欠かせないものとなっています。一方でAIを活用する企業や個人にもAIリテラシーの向上を促進する必要があり、日本がこれらの分野の産業競争に勝つために、経団連が2019年にAI活用戦略のためにガイドラインとして設定した指針がAI-Ready化ガイドラインです(参考: https://www.keidanren.or.jp/journal/times/2019/0221_02.html )。 AI-Ready化ガイドライン(出典: 日本経済団体連合会) AI-Readyはガイドラインで5段階のレベルに分けられており、それぞれの役職においての行動指針が記載されています。この指針に沿っていえば、レベル1の企業はそもそもAIの活用自体が議論のテーブルに上がっていない状態であり、逆にレベル5は全従業員がAIを活用しておりそれぞれのマーケット領域にAIの専門家がいる状態を表します。 まだ道半ばではありますが、LIFULLはこのガイドライン上でレベル3を達成しつつあります。実務へのAI活用を徹底する取り組み、社員へのAI教育をはじめ、AIへの投資が継続的にコミットメントされており、また独自のAI開発体制も保持しています。この投資を続けていき将来的に自然とAIやデータ活用がされる組織(会社)にしていくことで、事業課題解決の手段としてのAI活用が検討のテーブルに乗せられていけば、事業戦略の幅も徐々に広がっていくと考えられます。 AI活用促進チームのミッションと活動報告 以上のような背景におけるAI活用促進チームのミッションを紹介します。 AI活用促進チームのゴールは「 事業部とAI専門家のお互いの得意分野を活かした、具体的かつ良質なニーズや企画が量産される状態 」としています。そのゴールに対する打ち手として「人材育成・発掘」、「コンサルティング」に近い業務となりますが、具体的なミッションは大まかに以下の二つです。 AI活用のリテラシー・知見を全社に広める。 社内の事業ニーズに対する課題解決の手法として、AIの技術シーズを提案して導入につなげる。 チーム内のKGI(Key Goal Indicator)は「社内の事業ニーズに対するAI技術シーズの想定インパクト・導入確度の見積数」としています。AIを導入する企画段階においてどれくらいのインパクトが見込めるか、どれくらいの信頼度を持ってインパクトを出せるといえるかを見積もることで、AIの活用が事業課題解決の手段となるかの解像度が上がっていることを確認できる指標としています。 具体的な活動報告を以下に記述いたします。 AI学習Eラーニングサービスの受講促進 AI活用のリテラシー向上に取り組む上で、AIに関する基礎的な知識や活用事例を座学で学べるAI学習Eラーニングサービスを期間限定で社内に導入し、社員への受講を促進しました。 Eラーニングであれば業務の合間にでも耳で聴きながら受講することができることから、社員に対する学習負荷を最小限に抑えつつAIリテラシーの向上が図れることで、初学者の方でも取り組みやすいのではないかと考えました。ただし強制的に受講必須とするのは、本当に受講意欲のある社員に行き渡る前にサービスが終了してしまう恐れがあったため、受講希望者を優先する体制を整備しました。また、カリキュラムはメンバーの職種によってカスタマイズし、企画・エンジニア・バックオフィスなどそれぞれの職種に適した知見に関する講座を受講必須にする運用を実施いたしました。 この運用を約1年間弱行った結果、 運営側を除く総受講者数は87名、基礎カリキュラム100%達成者は29名 という結果でした。今回のEラーニング受講による効果を以下のように考察しています。 全社的なAIリテラシーの向上とAI導入の意欲向上に役立った。 各部署のAIに対する温度感を可視化することによって、今後のAI戦略室との関係性構築のベースとなるデータを取得することができた。 受講者が次の受講者を紹介してさらに受講希望者が増えていくような受講者ネットワークが構築され、全社的に広く告知ができた。 この活動を通して、後述するAI活用を目指す社内ニーズの発掘につながることになります。 社内の事業ニーズのヒアリング AIを活用するという議論の前に、そもそも解決すべき事業課題を深掘りしなければなりません。解決すべき課題は何か、現状のプロジェクト進捗はどのような状況か、見るべきKPI(Key Performance Indicator)は何か、その課題にAIを活用するとした際の利点は何か、AIを活用するとなれば達成すべき精度はどのくらいだと見積もれるか、などを深掘りすることによって、AIを導入した際の想定インパクトや導入確度を見積もることが可能になります。 現在AI活用促進チームでは、各部署の組織長に対して事業ニーズの深堀ヒアリングを行っています。いわゆる「コンサルティング」になるのですが、深掘りの過程で自部署が持っているAI技術シーズと事業ニーズのマッチングを検討します。ニーズにおける課題をAI技術シーズによって解決できそうかどうかを、簡易的なデモやプロトタイプを用意して実際に触ってもらうことで一緒に議論・検討します。 ただし、一方的に我々が持っている技術を売り込みに行ってもなかなか理解されないことが多いため、事業部と同じ指標で導入による想定インパクトを概算しておかなければなりません。この場合の指標は基本的に短期的な指標、例えば売上やCVRが挙げられますが、過去にAIの導入事例がないケースでABテストなどの実績もない場合、インパクトの概算が非常に難しいというのが一つの悩みポイントになっています。このようなプロセスの過渡期においては、どうしてもお互いの見ている数値が異なっているケースが多いため、直接のコミュニケーションによって目指すべきゴールをすり合わせていくことが重要となります。 まとめと今後に向けて AI戦略室ではLIFULLのAI-Ready化に向けてAI技術の活用を社内で促進していく「AI活用促進チーム」が結成され、「事業部とAI専門家のお互いの得意分野を活かした、具体的かつ良質なニーズや企画が量産される状態」をゴールとして打ち手を検討しています。それらの打ち手として、「1. AI活用のリテラシー・知見を全社に広める」「2. 社内の事業ニーズに対する課題解決の手法として、AIの技術シーズを提案する」の2点を重視し、日々の業務と並行して担当しています。 この記事を書いている現在、AI界隈では GPT-4 の自然言語処理モデルが世間を賑わせています。この波に乗り遅れないように、技術の革進を全社に広めていきたいと思います。 また、LIFULLでは共に成長できるメンバーを募集しています。この記事を読んでいただいた方は、ぜひこちらのページもご覧ください。 hrmos.co hrmos.co
検索エンジンチームにいながら外部公開APIのメンテナンスもしている加藤宏脩です。 この記事では、毎日大量に書き込まれ膨れ上がったMySQLのテーブルを、 テーブルローテーションさせることで不要なデータを継続的かつ安全に削除する処理の実装をしたのでそれについてお話したいと思います。 利用している技術 Amazon RDS for MySQL Engine version: 5.7.41 Amazon ElastiCache for Redis Engine version: 6.2.6 起きていた問題 LIFULLのとあるサービスは、アプリケーションとMySQL、DBの結果をキャッシュするRedisがあるというよくみる一般的なアーキテクチャで運用しています。 このMySQLのテーブルは毎日100万件以上のレコードが追加されていく状態になっており、 総レコード数は6億件を超え、容量は2TBを超えていました。 またMySQLの仕様もあり、不要になったレコードを簡単に削除することはできなくなっていました。 そのため、DBの空き容量が少なくなるたびにストレージを追加する運用を数年続けていました。 このままでは永遠にデータが増え続けてしまうので、不要な数億のレコードを削除して、今後も増え続けないようにする必要がありました。 問題解決を阻む課題 書き込みが継続しているテーブルへのレコード削除は不安定 MySQLのデフォルトのストレージエンジンであるInnoDBは、DELETE文を実行しても物理的な削除を行わずフラグメンテーションしてしまう仕様となっています。 サービスをとめずに解決するためには、 DELETE コマンドで不要なデータを削除したあとに下記のように、 ALTER TABLE コマンドを実行することでテーブルを再構築する必要があります。 ALTER TABLE tbl_name ENGINE=INNODB MySQLのドキュメント: https://dev.mysql.com/doc/refman/5.7/en/innodb-file-defragmenting.html 検証環境で上記コマンドを実行したところ、以下のことがわかりました。 初回のALTER TABLEの実行時間は12時間を超える 初回のALTER TABLEはテーブルをコピーするため容量が2倍の4TB以上必要になる InnoDB テーブルの online DDL 操作中に使用される一時ログファイルのサイズの上限設定値以上に書き込むと、 それまでのデータがすべて失われる。(innodb-online-alter-log-max-size) このアプリケーションのデータ書き込み量は不安定で、突然今までの2倍以上書き込まれる可能性がありました。 そのためサービスで利用しているテーブルのデータを削除して容量確保することは危険であり、 定期的に実行できるものではないことがわかりました。 DBごと移行することは、データの同期にラグができてしまい切り替え時に不整合が起きてしまう 上述の通り、運用しているDBに手を加えて解決することはできなかったため、新しく空のDBまたはテーブルを作り、 移行する処理を考えましたが、こちらにも課題がありました。 考えていた処理は以下の通り。 利用中のテーブルから不要なデータをDELETE文で削除する(この時点ではフラグメンテーションされているため空き容量は確保されていない)。 その後、新しくDBもしくはテーブルを作り、データの同期をする。 データの同期が終わり次第2で作ったDBもしくはテーブルに書き込みの向き先を切り替える。 このDBは絶えず激しく書き込みが行われているため、3の実行時に データの同期が完全に終わることがなく、DBの向き先を切り替えると 不整合が起きてしまうためできないことがわかりました。 書き込みを制限することは困難 本来、書き込みは一日数十万件にもなるようなものではなく、意図した設計とは違う使われ方をしていました。 アプリケーション側で書き込み数上限を設定することも考えました。 しかし、アプリケーションの利用者が社外にいるため 突然制限するわけにも行かず、 半年〜1年以上システムの改修対応をする期間を待つ必要があったため、書き込み制限は行いませんでした。 この問題に時間はかけられない データ量が多いため、レコード数の取得をするだけでも長時間かかります。 システムの状況を把握し検証をすると、数日かかってしまう状況でした。 本プロジェクト自体、チームのメイン業務ではなく、早くメイン業務に合流する必要があるため 時間をかけずにできるだけ早めに解決する必要がありました。 解決策 解決策は、 4つのテーブルを用意し3ヵ月ごとにローテーションし、 向き先のテーブルにデータが見つからなければ、前の時期のテーブルを探すように実装することでした。 こうすることで古いテーブルに書き込んで新しいテーブルにない状態でも不整合が起きなくなります。 さらに、2期間前のテーブルには完全にアクセスされなくなるため、 TRUNCATE するバッチ処理を実装するようにしました。 4つのテーブルの内訳は、下記の通りです。 現在の時期の向き先。読み書きするテーブル 1つ前の向き先。現在の時期の向き先にデータがない場合に呼ばれるテーブル 2つ前の向き先。読み書きされないため安全にデータを削除できるテーブル 次回のローテーションの向き先。 TRUNCATE 前にローテーションして新しいデータを書き込んでしまうのを防ぐためにある空のテーブル 結果、最小限の工数でサービスもやめず、DBの不要なデータを定期的に削除できるようになりました。 問題解決をするうえで着目したポイント レコードの有効期限は最長でも1ヵ月なのでそれ以降のデータはすべて削除できる データは一本釣りしかないので、向き先のテーブルにデータがなければ前の時期のテーブルから探しやすい 検索結果はRedisにてキャッシュするため、 同じレコードを取るために何度も向き先のテーブルと前の時期のテーブルにクエリが走ることは起きない 解決策の実装 アプリケーションの変更: 現在の向き先テーブルにデータが見つからなければ、古いテーブルを探すようにする DBの変更: 同じテーブルを数個用意する バッチの実装: 2期間前のテーブルを TRUNCATE する 他に考えていた手段 一本釣りのようなクエリが多くデータの賞味期限が短いことなどから、 MySQLのようなRDBの利用は妥当じゃないので、ほかのデータストアの利用を検討していました。 前段に検索結果をキャッシュするRedisがいるので、 Redisを永続的なデータストアとしても使えるAmazon MemoryDB for Redisを検討していました。 今回は工数の関係で解決策に記載している方法をとりましたが、 まだ諦めていないのでAmazon MemoryDB for Redisに変えてみたいと思っています。 感想 6億レコードを超えたMySQLのテーブルを継続的かつ安全に削除する処理の実装をした話でした。 読んでいただきありがとうございました。 フラグメンテーションの問題を回避しつつ、 サービスをとめることなく 完全にアクセスされないデータを削除できるようになりました。 このような泥臭い作業は軽視されがちですが、 積み重ねることでシステム運用の負担を減らせて、開発者が本来の力を発揮しやすくなるのだと考えています。 ひいては LIFULLのビジョン実現につながるのだと思います。 最後に、 このような効率化をしたいまたは得意なエンジニアの方々、 LIFULL では一緒に働く仲間を募集しています。この記事を読んで LIFULL に興味ができた方は求人情報も御覧ください。 hrmos.co hrmos.co
こんにちは、LIFULL社内アワード運営チーム「クリエイティブアワード委員会」のチバです! 今回は、「未来につながるクリエイティビティの創出」をビジョンに掲げ社内アワード運営などを行う社内組織、「クリエイティブアワード委員会」の活動紹介です💪❤️🔥 クリエイティブアワード委員会とは? 私たちのミッション プロジェクトアワード2022の取り組み グランプリを選び出す必要性は果たしてあるのか? 目標の成果指標を考える Zoomの参加者エクスポート機能で計れるもの Googleフォームを投票フォームにして計れるもの プロジェクトアワード2022の結果 デザイナーの伊藤さんの取材記事 クリエイティブアワード委員会とは? 部署関係なく、有志メンバーで構成されている会社公認のワーキンググループです。 社内の表彰制度「プロジェクトアワード」の運営を主な活動にしています。 「プロジェクトアワード」とは、 「日々の業務成果」を社内にお披露目して多くのプロジェクトにスポットライトを当てる取り組みです。 在籍メンバーは通常業務が他にあり、私自身も、普段は LIFULL HOME'SのLINE・メールのリテンションマーケティング をしています。 私たちのミッション 主管に人事本部がついており、私たちは以下のミッションを与えられています。 LIFULLの創り出すアウトプットの品質ベンチマークを高めることを狙いとして、仲間の取り組みに称賛する機会を生み出す 上記を活動目標に落とし込むと、下記の3つになります。 アウトカムを生み出すまでのプロセスが社内に知見共有として拡散される機会をつくる 他チームの取り組みを知る"面"を増やして、部署を越えた協働のきっかけをもたらす 社員が社員に「期待」や「感謝」を「称賛」として伝えられる場を用意する 上記の目標をどのように施策に置き換えて取り組まれたのか、 プロジェクトアワード2022 開催の様子とともにご紹介します💁 プロジェクトアワード2022の取り組み プロジェクトアワードは社内で毎年開催されるイベントです。 「日々の業務成果」を社内にお披露目し、最も称えられたプロジェクトはグランプリを受賞してオリジナルグッズを手にすることができます。 グランプリ選抜は、社員全員が投票で選ぶことになっており、これは、2006年にボトムアップではじまった頃から変わらない方針です。 2006年 ものづくりの素晴らしい仕事を評価する、トップセールスと対をなす存在として誕生してから、2022年 「プロジェクトアワード」一次審査に審査員制度を導入、社員投票は二次審査実施へ変更した グランプリを選び出す必要性は果たしてあるのか? そもそも、どのプロジェクトも素晴らしい取り組みであるのにグランプリを選び出さなくてもよいのではないか、とリプレースをかけようとした時期もありました。 しかし、プロジェクトアワードを開催すると、社内中の優れたプロジェクトがわっさわっさ集まってきます。 「知らなかった、こんな利点があったのか」 「この取り組みは知ってたけど、うちのプロダクトには関係ないと思ってた、そんなことないじゃん」 「これの話はもっと聞きたい・・・!担当者とつながるぞっ」 普段から社内各所のプロジェクトや施策情報はあらゆるチャネルで共有されています。 LIFULLでは、毎月の全社総会、本部長主催のウェビナー、Slackや掲示板に投稿される社内報などで知ることはできます。 しかし、スポットライトが当たることで注目が集まりやすくなりました。 ピックアップするだけで、知の拠点ができあがる のです。 ならば、ピックアップしなければ。私たちがやることだ、そう思えたので活動を継続することになりました。 目標の成果指標を考える 上述した3つの目標、それぞれには以下のような成功指標を与えました。 これらの成果指標は、それぞれ下記の方法で計測しました。 Zoomの参加者エクスポート機能で計れるもの 最終プレゼン審査会参加人数 継続視聴時間 参加者所属部署比率 Googleフォームを投票フォームにして計れるもの 投票総数 ユニーク投票数 投票コメント数 ここまでいったら成功、が明確になったことで、これらの指標を押し上げることを意識した活動ができるようにしました。 過去トラッキングできている投票総数、ユニーク投票数、投票コメント数の3つを過去2年と比較すると、やはり例年よりも成長を実感できます。 見える指標が出来上がることで、グンッと自律的に動けるようにもなったので、チームメンバーが自らタスクを取りにいき進めやすくなりました。 プロジェクトアワード2022の結果 プロジェクトアワード2022では、社内デザイナーによって製作されたオリジナルグッズが景品となりました。 デザイナーの伊藤さんの取材記事 note.com グッズ化アイディアも、並行開催したアイディアアワードで一般社員から公募したものです👏 電源タップもヘッドホンもUSBハブも入るゆとりの16インチサイズ ウィンクしてるホームズくんでディスプレイも常にきれいにできちゃうぞ! フリーアドレスになったオフィス移動もこれで安心安全👷 実際に受取った社員も喜んでくれて、運営チーム一同安心しています。 note.com これからも仲間の取り組みに称賛する機会を生み出せるよう努めてまいります💪 次の活躍にご期待ください!
こんにちは! LIFULLエンジニアの吉永です。 普段はLIFULL HOME'SのtoC向けのCRMチームにてエンジニアリングマネージャをやっています。 本日はクリーンアーキテクチャで構築したプロダクトが初版リリースから2年経過した現在、どうなっているか?について紹介したいと思います。 これから新規プロダクトにクリーンアーキテクチャを採用しようとしている方々の参考になれば幸いです。 アジェンダ クリーンアーキテクチャで構築したプロダクトの概要 クリーンアーキテクチャを採用して得られたメリットやデメリットについて 2年経過してみて今どうなの? まとめ クリーンアーキテクチャで構築したプロダクトの概要 今回のブログで紹介する我々のプロダクトですが、オムニチャネル戦略を推進する為の各種機能を提供するAPIサーバーとなり、下記のような機能を持っています。 LINE/Mailでその日の新着物件情報をユーザーが希望した検索条件に応じて通知する機能 LINE/Mailでユーザーが問合せた物件に近い条件の物件をレコメンドする機能 LINE公式アカウントでユーザーとトークルームでインタラクティブなやりとりを行い、シナリオ配信やレコメンド物件配信を行う機能 各種サービスとSalesforce社のService CloudやMarketing CloudとのAPI通信を仲介する機能 言語はGoを採用 これらの機能を構成するにあたりクリーンアーキテクチャを採用しており、有名な下記の図にならった形で各レイヤーを構成しています。 出典:The Clean Code Blog https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html なお、このプロダクトにクリーンアーキテクチャを採用した当時はチーム内でクリーンアーキテクチャ及びGoの実装を経験したメンバーはおらず、書籍やWeb、社内で先行採用されていたプロダクトの実装を参考に見様見真似で実装しました。 開発初期は実装もレビューもキャッチアップに時間がかかっており、新しい言語、新しいアーキテクチャによる実装で非常に苦労したことを覚えています。 クリーンアーキテクチャを採用して得られたメリットやデメリットについて どんなアーキテクチャにもメリット・デメリットはありますが、クリーンアーキテクチャにおいても同様で、実際に採用してみて個人的に感じたことを紹介します。 メリット 各レイヤーの責務をアーキテクチャで示してくれているのと、各レイヤーはインターフェースに依存するように設計するので自ずと各レイヤーが疎結合になり、ユニットテストを行いやすい。 ユニットテストを行いやすいので、テストコードを実装するのがあまり面倒にならず、結果的に変更に対する品質の担保をしやすい為、安心して変更できる。 レイヤー間の独立性が高いので、インタフェースさえ設計してしまえば、各レイヤーの実装を別々の担当で並行に作業を進めやすい。 クラス設計に迷ったときにクリーンアーキテクチャという指針があるので、チーム内での議論があまり散らばらず収束しやすい。 指針は示してくれているが、かと言ってガチガチに固まっているアーキテクチャではないので、ある程度は自分たちの開発に特化している形に実装してしまっても、大枠のレイヤー構成や依存ルールさえ守れていれば拡張性と保守性を高く保つことができる。 レイヤーが疎結合になることで、各レイヤーの実装のシンプルさが保たれるので、ソースレビューしやすい。 デメリット 小さな機能追加でもアーキテクチャ内の登場人物が多いので、クラス数が増え、煩雑になりやすい。 基本的にインターフェースに依存するので、IDEでメソッドの「定義へ移動する」際に、たいていのIDEでは定義だとインタフェースに飛んでしまい、メソッドの実態へ飛ぶには「実装へ移動する」を選択する必要があるので、コード内の移動に少しだけストレスを感じることがある。※それはあなたのIDE環境の問題でしょうというご意見もありそうですが エンティティレイヤーは「ビジネスルールをカプセル化したメソッドのあるオブジェクトやデータ構造と関数の集合」を実装するレイヤーなので、DBの1レコード分のデータをマッピングするだけで、アクセッサー以外のメソッドを持たない単純なオブジェクトと複雑なビジネスロジックを実装したオブジェクトが混在することもあり、適切にパッケージなどで分けないと煩雑になりやすい。 2年経過してみて今どうなの? ステップ数 初版リリース後、様々な機能を追加していったので、リポジトリ内のステップ数は2年間で約3倍になりました。 テストカバレッジ 初版リリース時は自動テストコードのカバレッジは80%程度でしたが、初版リリース後3ヶ月ほどかけて98%まで上昇させ、その後現在に至るまでこの水準を維持しています。 これは、新規追加ファイルのテストコードもなるべくカバレッジは100%を目指そうという方針で開発を進めてきたので、チームの皆で意識して取り組んでいる結果、維持できていると思います。 レビュー 新しくエンドポイントを実装する際はまずクラス図をクリーンアーキテクチャの各レイヤー図にあてはめて作成し、各レイヤー間のインタフェース仕様と追加・変更するクラスを設計レビューしています。 この時点で大枠の設計を固めており、以降の実装フェーズでは基本的にどのレイヤーから実装しても良いようになっている為、実装者が手を付けやすい個所から実装することが出来ています。 メリットでもあげましたが、レビュアーからすると各レイヤーが疎結合でシンプルに実装されている為、レビューはしやすいと思います。 まだ本格的には運用できていないのですが、直近ではPRの変更行数をなるべく抑え、レビューしやすい粒度にPRを分割しようという取り組みもあり、以前だと新規エンドポイント実装時はコントローラー層からドメイン層まで一気に実装してからまとめてレビュー依頼をしていましたが、今後はコントローラーとコントローラーのテストコード、テストコード内で利用するユースケースのモックで1PR、それが終わったらユースケースとユースケースのテストコード、テストコード内で利用するリポジトリやドメインのモックで1PRというようにある程度レイヤーで区切ってのレビューを試してみて、レビュー負荷の軽減ができそうかを検証していこうと思っています。 ※もともとクリーンアーキテクチャで実装されたソースはレビューしやすいと感じていたので、1PRで確認する対象が減ると見逃しも減り、対象へより集中してレビューできると思うので、PRサイズの削減を検討しています 改修のしやすさ 改修はしやすいです。 理由としてはメリットでも挙げた、単体テストを実装しやすい為、既存のコード変更があまり怖くなくなっていることと、各レイヤーが独立している為、例えば新規でエンドポイントを追加する際にも、既存のリポジトリやユースケースのインタラクターを再利用しやすく、コントローラーだけを新規で作成すれば良いといった場面もあり(もちろんその逆もありますが)、インタフェースに依存するようにプログラミングしておくことのメリットを最大限享受できていると思っています。 また、言語も静的型付けであるGoを採用していることもあり、各レイヤー間のインタフェース変更も型が一致しなくなってコンパイルエラーになってくれるので、改修漏れが発生しないことは良いことだと思います。 直近だと、分散トレーシング対応をする為に、コントローラーからエクスターナルまでContextオブジェクトを伝搬させる為のリファクタリングを進めているのですが、コンパイルエラー除去と単体テストの修正を行えば安心してリリースできる状態であることが、開発者がストレスなく開発できていて、開発者体験向上にも一役買ってくれていると実感しています。 余談になりますが、LIFULLではKEELというプラットフォームで分散トレーシングする為の基盤を提供してくれていて、アプリケーションレイヤーで少しだけコードをいじるだけ簡単に複数サービスのログを統合して閲覧できるようになっているので、下記の記事も良かったら見てください。 www.lifull.blog qiita.com まとめ クリーンアーキテクチャを採用したプロダクトが2年経過してみて今どうか?について紹介しました。 正直ネガティブな感想はあまりなく、今後数年に渡って改修を続けていってもあまりゆがまずに済むのではないか?と思っています。 もちろん、初期構想時と比べると、いくつかパッケージ分けが適切じゃないかもとか細かい個所で修正したい個所はあるものの、大枠でみていくとクリーンアーキテクチャで実装したからこそカオスにならずにある程度秩序が保たれていると思います。 また、クリーンアーキテクチャで実装することで、 SOLID原則 に自然と準拠していき、今まで理解があやふやだったSOLID原則が少し理解が深まったと思うので、そういった面でも一度触れてみることは良いと思います。 これからクリーンアーキテクチャを採用してプロダクトを開発しようとしている方々へ少しでも参考になれば幸いです。 最後に、LIFULLでは共に成長できるような仲間を募っています。 よろしければこちらのページもご覧ください。 hrmos.co hrmos.co
LIFULLでフロントエンドエンジニアをしている齋藤です。 2008年入社なので15年目ぐらいの古株です。今は LIFULL HOME'S の賃貸部門でフロントエンド開発をしています。 いきなりですが、みなさんはアイコンをどう実装していますか? アイコンフォント、スプライト、一つ一つ切り出す。フォーマットもSVG、PNG、Fontなどなど。 実装方法はいろいろありますし、サイト規模や運用体制などでどれが扱いやすいかは変わってきますよね。 たかがアイコン、されどアイコン。 利用頻度が高く、大きさや色が微妙に違ったりすることも多くてこれまでいろいろと試行錯誤してきました。 そこで今回はLIFULL HOME'Sでどんなアイコン実装が行われてきたかを振り返ってみたいと思います。 これまでの歩み。 都度一つ一つ切り出しての対応 スプライト画像での対応 SVG symbolを利用した対応 data-url化したSVGをimgタグのsrcに埋める対応 番外編:SASSでSVGをdata-url化してbackground-imageで読み込む 終わりに これまでの歩み。 都度一つ一つ切り出しての対応 15年ぐらい前、このころはデザインが上がってきたら一つ一つ切り出して対応していました。 共通化はしていても色が違う、大きさが違うとなれば都度切り出して作成が必要でした。 すでにあるこの大きさじゃダメなのなんて思いながら渋々切り出して対応していたものでした。 スプライト画像での対応 11年ぐらい前、リニューアルを機に新たに設計していく中でアイコンはスプライト画像化を選択しました。 ui-icon という汎用classを作り、アイコンの指定にはもう一つ ui-icon-hoge のように一意のclassを作って対応しました。 すでに作られた画像であれば <span class="ui-icon ui-icon-hoge"/> という感じでHTMLを書けば良かったので格段に楽になりました。 大きさも文字サイズ連動するように作っていたのでフォントと同じように扱えたのも良かった点でした。 また、画像置換の手法を入れていたので空要素としてだけでなくテキストを含めることもできたので、アクセシブルな作りでもありました。 難点は色が違うアイコンだけはスプライト画像を修正して追加しなくてはいけなかったことでした。 // CSS .ui-icon { display : inline-block ; width : 1em ; height : 1em ; line-height : 1 ; background : url( 'sprite_icon.png' ) no-repeat 0 0 / 1em 54em ; text-indent : 1em ; overflow : hidden ; white-space : nowrap ; } .ui-icon-history { background-position : 0 0 } .ui-icon-favorite { background-position : 0 -1em } SVG symbolを利用した対応 7年ぐらい前、このころになるとブラウザのSVG対応も安定してきたのでSVGを活用し始めました。 具体的には、 <body> 直下に利用するSVGのsymbolを置き、利用する箇所でSVG useして利用するというものでした。 SVGなので大きさだけでなく色に関しても可変性があり、ここでついに色・サイズ違いの再作成という呪縛から解き放たれました。 利用する場合にはSymbol IDと色、大きさを指定するだけのtwig macroを準備したのでそれを利用するだけとお手軽になりました。 inline SVGだからこそできるCSSからの色指定も重宝しましたね。 今現在もこれが現役で利用されています。 // Twig 内での利用方法 {{ svg.use('history', '32', '#000', 'title') }} // Twig macro {% macro use(id, size, fill, title) %} {% if title %} {% set aria %}role="img"{% endset %} {% else %} {% set aria %}aria-hidden="true"{% endset %} {% endif %} <svg width="{{ size }}" height="{{ size }}" {{ aria }} focusable="false"> {% if title %} <title>{{ title }}</title> {% endif %} <use xlink:href="#{{ id }}" aria-hidden="true" {{- fill -}}></use> </svg> {% endmacro %} とはいえ課題も出てきました。 運用としては必要なsymbolのみを必要なページで埋めるということをしてきました。 ところが、ページも増え、長年の運用による複雑さも増してきた中でどこのページにどのsymbolが必要なのかが把握できなくなってきたのです。 symbolを置く場所と利用する場所の距離が離れているのが一つの原因でした。 利用しているコンポーネントが読み込まれたらsymbolを埋め込む等ができたら良かったのですが、それもそう簡単ではないので別の方法を準備することにしました。 data-url化したSVGをimgタグのsrcに埋める対応 そして今。上記課題を解決しつつ、作り上げた資産(SVG)も有効活用できる方法として、SVGをdata-urlに変換してimgタグのsrcに埋めるmacroを新たに作りました。 これによりsymbolの読み込みが不要になり、上で挙げた課題解決への一助となる狙いです。 課題解決への一助と書いたのは、既存のsymbol利用をやめるわけではなく併用するからです。 当初は既存macroを書き換えてしまおうと考えていたのですが、symbol利用で書いた通りCSSからの色指定は重宝しているのでこれをなくすことはせず、併用という道を取りました。 // Twig macro {% macro img(id, size, color, alt) %} {% import _self as svg -%} {% set replaceMap = { '<': '%3C', '>': '%3E', '#': '%23', '{': '%7B', '}': '%7D', ' ': '%20', '"': "'", } -%} {% set src = 'data:image/svg+xml,' ~ svg.svg(id, size, color)|replace(replaceMap) %} <img src="{{ src }}" width="{{ size }}" height="{{ size }}" alt="{{ alt }}"> {% endmacro %} {% macro svg(id, size, fill) %} <svg xmlns="http://www.w3.org/2000/svg" width="{{ size }}" height="{{ size }}"> <def> {% include 'Bundle:Assets:svg/icon/_' ~ id ~ '.svg.twig' %}{# svg symbol file #} </def> <use href="#{{ id }}" {{- fill|raw -}}></use> </svg> {% endmacro %} 番外編:SASSでSVGをdata-url化してbackground-imageで読み込む 実はこのdata-url化という手法は以前からSassで利用していました。 Twig同様にSVGコードを渡したらdata-urlに変換して返す関数を作って実現しています。 SVGコードをencodeして data:image/svg+xml で返す。 TwigでもSassでもやっていることは一緒ですね。 // Sass @function svgUrlEncode( $svg ) { $replaceMap : ( '<' : '%3C' , '>' : '%3E' , '#' : '%23' , '{' : '%7B' , '}' : '%7D' , ' ' : '%20' , "'" : '"' , ); @each $s , $r in $replaceMap { $encode : string.str-replace( $s , $r , $svg , true); } @return $encode ; } @function svgDataUri( $svg ) { $svg : svgUrlEncode( $svg ); @return url( 'data:image/svg+xml;charset=utf-8, #{ $svg } ' ); } 終わりに いかがでしたでしょうか? やり方はほかにもいろいろありますが、言語やブラウザの対応状況等のタイミング、使える時間というのもあってこういった変遷をたどってきました。 技術の進歩やその時の課題・状況に合わせ最適解を探す。 今後も課題解決をしながらサイト機能や開発効率などの改善に取り組んでいきたいと思います。 最後に、LIFULL ではともに成長していける仲間を募集しています。よろしければこちらのページもご覧ください。 hrmos.co hrmos.co
プロダクトエンジニアリング部の海老澤です。 普段は LIFULL HOME'S の賃貸部門のフロントエンド開発をしています。 近年、LIFULL の開発部門では「開発生産性」という言葉が取り沙汰されるようになりました。 LIFULL HOME'Sの主要リポジトリは10年以上運用され続け、今も多くの開発者によって日々改修され続けています。 長い年月の中で小さな設計ミスも積み重なって大きくなり、ちょっとした実装でも入念な調査が必要となり開発生産低下の要因となっていました。 また10年以上前に採用したフレームワークで稼働しているため、今ではドキュメントを探すのも一苦労という具合です。 そこで主要開発部門では「自部門の機能はマイクロサービスへと切り離し、各々で面倒を見る」という方針になりました。 賃貸部門も同様に機能の切り離しを始め、先日「物件詳細ページ」のマイクロサービス化を行いました。 今回はマイクロサービス化にあたり新基盤の技術選定をしたので、実際触ってみた感想などを交えながら紹介していければと思います。 画面のビフォーアフター マイクロサービス化と同時にUIのリニューアルも検討、開発中です。 旧UI 新UI ※キャプチャは開発中の画面です。 旧基盤ではダイナミックサービングでPC/Tab用・SP用のレイアウトを切り替えていましたが、新基盤ではレスポンシブデザインへと変更しました。 デバイス間のデザインルール・トンマナの差分をなくすこと、開発生産性を上げ改善スピードを上げるのが狙いです。 新基盤の全体構成 今回は Web アプリケーション部分のみ刷新を行いました。API は全社で使っている既存のものを使っています。 新基盤の構成図 ここからは技術選定についての詳細を書いていきます。 バックエンド バックエンド 技術選定のモチベーション 社内で標準採用されている言語・技術であること これは組織の課題でもあるのですが、LIFULL はエンジニアの部署異動がそこそこあります。 社内では技術集約の観点で標準技術が定められてるのでそれに従いました。 技術選定で「挑戦」しないこと LIFULL HOME'S の賃貸部門は LIFULL の中でも中核を担う組織で、ほかの開発チームに比べて規模が大きいです。 それゆえに人員の入れ替えも顕著で、さまざまな技術スタックを持った人がいます。 そういった中で目新しいフレームワークを用いるとドキュメントや知見不足に悩むことがあります。 有識者がチームに必ずいるのであれば良いのですが、チーム編成の都合上難しい場合もあります。 そうなってしまった場合、開発はつまずきがちになりますしコードの品質も落ちることが過去の経験則から容易に想像できました。 このような事態を避けるために我々は技術選定で「挑戦」するのをやめ、学習コストの低いフレームワークを採用することを選びました。 採用技術 上記のモチベーションを踏まえ、バックエンドは以下を採用しています。 アーキテクチャ: Clean Architecture フレームワーク: Express x TypeScript アプリケーション実行基盤: 内製ライブラリ「KEEL」 アーキテクチャ: Clean Architecture LIFULL のバックエンド刷新プロジェクトで採用されたアーキテクチャです。 それが社内に広まっていて知見も溜まっているため、今回 Clean Architecture を採用しました。 www.lifull.blog 情報を表示するだけの Web アプリケーションで Clean Architecture は冗長ではないかという意見もありましたが、レイヤごとの責務・規約がはっきりしており制約が厳しいことから開発者によるブレが少なくなることが見込めます。 実際業務で触ってみたときも「どこに何を書けばいいのか」というのが分かりやすく、設計しやすいのは魅力だと感じました。(実装の「詳細」「抽象化」まわりの理解はちょっと大変でしたが……😇) フレームワーク: Express x TypeScript 言わずと知れたバックエンドフレームワークです。 日本語ドキュメントや記事、ライブラリも充実しているため学習コストを低く抑えることができます。 型の恩恵は受けたかったため TypeScript も導入しています。 TypeScript は社内でも導入事例が多くすんなり決まりました。 今の所は複雑な型推論は必要としておらず、素直にコードを追えば型がわかるため安心感があります。 バックエンドとフロントエンドで言語を共通にできるのも良い点だと感じました。 アプリケーション実行基盤: 内製ライブラリ「KEEL」 実行基盤は全社で利用している内製ライブラリ「KEEL」を活用しています。 デプロイやログ吐き出しなど日々の運用タスクを吸収してくれるすばらしい基盤で、 KEEL のおかげでアプリケーション開発に集中できています。 当ブログでもよく記事があがっていますので詳細は割愛しますが、ぜひご覧ください。 www.lifull.blog フロントエンド フロントエンド 技術選定のモチベーション メンテナンスコストが軽いこと まず第一に、LIFULL HOME'S は複雑な操作やインタラクションを必要としないポータルサイトです。 クライアントが入稿した情報の表示がメインで、ユーザーの操作によって画面が大きく変わるということがほとんどありません。 そういったサイトを開発していくうえで React や Vue を用いるのは冗長だと考えました。 実際アップデートの頻度も高くメンテナンスコストが嵩みますし、ビルドプロセスも必須です。 今後さらにイケているフロントエンド技術が出てきた際に引き剥がしにくいという欠点もあります。 前身のメインリポジトリは10年以上稼働していますが、 ソースコードの規模が膨大すぎること、依存関係が大きいことからアップデートが非常に困難になっています。 今回の新基盤は何年稼働するか分かりませんが、少なくとも5年以上は開発されるでしょう。 そうなった時にメンテナンスコストが軽いというのは大きなメリットとなります。 開発者のスキルに左右されないこと バックエンドの技術選定でも触れましたが、賃貸開発部門は規模が大きく人員の入れ替えも顕著です。 常に複数のチームが稼働しており、同じページを並行開発していることもあります。 HTML/CSS/JavaScript に明るくないコーダーやバックエンドエンジニアがフロントを触ることも多々あります。 そういった際に学習コストの高い React や Vue だと逆に開発の遅れを招いたりレビューコストが高まるという懸念もありました。 そのため、なるべく平易で学習コストの低い技術を採用しています。 後述する Tailwind CSS や Stimulus は比較的最近のフレームワークですが、ドキュメントが簡潔かつできることも限られているため1日あれば手に馴染む技術です。 フロントエンド 採用技術 これらのモチベーションを踏まえ、フロントエンドは以下を採用しました。 HTML: Preact x TypeScript で HTML を生成し Express でサーバサイドレンダリング CSS: Tailwind CSS JavaScript: Stimulus HTML: Preact x TypeScript Preact x TypeScript で Express から素の HTML を返却しています。 Preact の選定理由としては軽量であること、型が使えることです。 我々は HTML をレンダリングしたいだけなので React のような重いライブラリは冗長でした。 とはいえ型情報は付与したかったので、 tsx 形式が使える Preact を採用しています。 クライアントサイドの振る舞いは前述の Stimulus を利用するので Preact はテンプレートエンジンとしてのみ利用しています。 これは別のテンプレートエンジンに差し替えたくなったときに載せ替えを容易にするためでもあります。 CSS: Tailwind CSS Tailwind CSS はユーティリティファーストな CSS フレームワークで、非常に小さい単位の CSS クラスを HTML に直接書いて組み合わせることでスタイリングをします。 従来の課題として、HTML と CSS の概念的距離が遠いという問題がありました。 普通にコーディングを行おうとすると HTML に適当なクラス名を振って別途 CSS でそのクラスに応じたスタイルを書き、HTML 側でその CSS を読み込むという手間が発生します。 Sass の登場で CSS を書くのはいくらか楽になりましたが、概念的距離の圧縮まではいきませんでした。 Vue のように SFC でやるという手もありますが、それでもクラスの命名という一番面倒で退屈な作業は残ってしまいます。 Tailwind CSS はすでに用意されているクラスを組み合わせて使うので命名という概念がなく、 HTML にガンガン書いていけるので概念的距離をゼロにできます。 また、クラスの単位が非常に小さいのでカスタマイズ性も高く、デザインの再現も容易です。 HTML を見るだけである程度見た目が想起できるというのも魅力的ですね。 頻出スタイル(ex: ボタンデザイン)は @layer component へ切り出して使っていますが、ごく少数ですし1ファイルにまとめているので何個も CSS ファイルを開くこともありません。 体感ですが CSS を書いていたころよりも倍以上のスピードでコーディングできるようになったと感じています。 素 CSS/Sass を書くときは少し憂鬱になります。 JavaScript: Stimulus 前述したように、LIFULL HOME'S は物件情報を載せるポータルサイトでありユーザーの複雑な操作を必要としません。 そのため js で与えるべき振る舞いも少なく、再利用できる動きがとても多いです。 そういった振る舞いを共通化する際、React や Vue でコンポーネント化して再利用するというのが考えられます。 しかし表示箇所によって少しデザインが変わるだけで HTML や CSS クラスの分岐が発生してコンポーネントが肥大化していくという問題があります。 Slot や Mixin を使いこなせばそんなことにはならないかもしれませんが、大規模な開発組織でそれらの統率をとっていくのは非常に困難です。 そこで我々は 37signals 謹製の JavaScript ライブラリ Stimulus を採用しました。 ドキュメント にもあるように、Stimulus はちょっとした振る舞いを HTML に与えるライブラリです。 HTML に data-controller とそれに付随するデータ、アクションを書くことでイベントを貼り付けることができます。 Stimulus の旨味は Controller を複数アタッチできること、DOM 構造に縛られないこと、イベントアタッチの処理が不要なこと です。 再利用性の高い小さな Controller を作っておけば HTML がどんな構造・デザインであろうとアタッチすれば動きますし、複数組み合わせると複雑な動きも作れます。 また、HTML と js の結合で一番面倒なのが addEventListener の処理かと思いますが、 Stimulus は MutationObserver で DOM を監視しており HTML が画面に出現するだけで 自動で該当の Controller のイベントがアタッチされます。 これは非常に強力で、サーバサイドから Stimulus Controller が設定された HTML を返却すれば Ajax で画面を一部更新しようと勝手にイベントがアタッチされるため js の読み込み忘れで画面が壊れた〜という心配もありません。 同様に DOM が消えれば removeEventListener されるのも安心ポイントです。 今回の新基盤ではオートローダーの仕組みも導入しているためページごとに読み込む js を bundle する必要もありません。たいへん快適です。 弊社エンジニアの Qiita 記事でも紹介しております。 qiita.com 再利用性の高い Stimulus Controller が充実してくると HTML に既存 Controller を書いていくだけで振る舞いの実装が終了するため、js を書くことがほぼなくなります。 実際、新基盤が稼働してから数ヵ月機能追加・画面改修をしていましたが、ほとんど js は書いていません。 コードは書くほど負債になると言いますが、きちんと設計すればするほど資産になっていくのも Stimulus の魅力だと感じます。 過去の記事でも話題にしていますので、ぜひこちらもご覧ください。 www.lifull.blog テスティング テスティング 技術選定のモチベーション テスティングに関してはそこまで大きい課題感はなかったのですが、 UnitTest を速く実行できること、E2E テストを書きやすくするのは意識しました。 テスティング 採用技術 UnitTest: Vitest E2E: Playwright UnitTest: Vitest Vitest は Vite の設定をそのまま使えるテスティングライブラリです。 今まで弊社の TypeScript 環境では Jest を採用していて最初はそれに倣っていましたが、 開発中に Vitest がよいぞとなり乗り換えをしました。 書き味は Jest とほぼ同様ですが実行速度が桁違いで、爆速で UnitTest を回せます。また、config も非常にシンプルで設定がとても楽ちんです。 Vite を使っているわけではないので全恩恵を授かっているわけではないのですが、実行速度が速いというだけで爆アドだと思います。 乗り換え自体もとても簡単にできたので、Jest を使っている方はぜひ Vitest もご検討ください。 E2E: Playwright Playwright は Microsoft 謹製の E2E ライブラリです。 TypeScript に標準対応しているのが魅力的で、難しいセットアップをせずとも導入が可能です。 公式ドキュメント も充実しており、「こういうことがやりたいな〜」というのはたいてい Guide にそろっているので安心感があります。 主に旧基盤と新基盤の情報の表示差分確認や package bump 時のビジュアルリグレッションで活用していて、テスト工数の削減に役立っています。 まとめ まだ新基盤が稼働して数ヵ月しか経っておりませんが、旧基盤と比べて圧倒的に開発しやすく生産性が高まっているのを感じています。 実際稼働から何名か新規メンバーが入りましたが、そこまで苦労せず開発できているようです。 LIFULL HOME'S はまだまだ成長していくプロダクトです。 今回の基盤刷新をきっかけにより良い価値をユーザーに届けてまいります💪 最後に、LIFULL ではともに成長していける仲間を募集しています。よろしければこちらのページもご覧ください。 hrmos.co hrmos.co
エンジニアの加藤です。LIFULL HOME'Sの注文住宅領域を支えるエンジニアチームのマネジメントを担当しています。 LIFULLでは定期的に エンゲージメントサーベイ を実施し、組織の状況把握を行っています。 しかし、エンゲージメントサーベイは全職種共通のフォーマットとなるため、「開発のしやすさ」や「プロジェクト進行」などエンジニア特有の課題までは特定しづらく、さらに深掘った分析が重要です。 こうしたエンジニア特有の課題発見や課題の深掘りを効率的に行うため、「ネガティブミーティング」を企画し実施したので、そちらを紹介したいと思います。 ネガティブミーティングとは 弊社では課題を出し合う話し合いを「ネガティブミーティング」と称して実施しています。 ここでは解決策などは議論せず、ひたすら「コト」に向けて率直な課題を挙げることに集中します。 また、ネガティブミーティングで出た課題の打ち手は別途「ポジティブミーティング」と呼ばれる話し合いで議論し、課題解決の実行まで落とし込みます。 我々はこれら2つを組み合わせて「ネガポジミーティング」と称し、セットで実施しています。 ネガティブミーティングの特徴 ネガティブミーティングは、課題だけを挙げるミーティング 課題を出すことだけに集中するため、普段だと言いづらい反対意見や代替意見も思い切って伝えることができる ネガティブな内容でも、意見を出すことを楽しむ ポジティブミーティングの特徴 ネガティブミーティングで出た課題の解決策を決めるミーティング 実行する解決策を決めたら「誰が」「なにを」「いつまでに」を決める ワークの流れ 今回のワークでは3, 4名ずつのチームに分かれ、以下の流れに沿ってネガティブミーティングを実施しました。 誰かが「ここがつらいよ〇〇」を決める(例:ここがつらいよ目標設定) みんなで「その心は〜」をひたすら出す(例:その心は、エンジニアの成果の定量化がキツい) 意見を出し切ったら1に戻る 今回のようなワークではより多くの観点で課題を出し合うことと、チームメンバー全員が話し合いに参加することが重要です。 そのため、1のテーマ設定は一人ずつ持ち回りで行うよう工夫しました。 また、ネガティブミーティングでは出てきた課題に対し悲観的になるのではなく、むしろ課題が浮き彫りになったことを前向きにとらえることも重要です。 最後は笑顔で終えられるしくみとして、チーム内で最も共感された課題を川柳(または短歌)にまとめ、全体へ共有してもらうこととしました。 やってみた結果 今回は約30分のワークにて実施しましたが、50を超える課題を発散したチームもあり想像以上の結果が得られました。 大きく分けると「開発プロセス」、「プロジェクト進行」、「技術的負債」、「プロダクト」、「目標・評価・キャリアパス」についての課題が多く挙がり、狙いであったエンジニア特有の課題発見と深掘りが実施できたと感じています。 また、どのチームも楽しみながら課題を出し合えていたように見受けられ、この後実施する課題解決にも前向きに取り組んでいける印象を抱きました。 組織課題のようなネガティブな意見は心理的安全性が担保された環境でなければなかなか言いづらいものです。 ネガティブミーティングのフレームでは課題を出し合うことだけに集中することが前提となるため、そういった環境づくりに効果的であると感じます。 まとめ 今回はネガティブミーティングを通じて組織課題を発散する取り組みについての紹介でした。 今後はポジティブミーティングを開催し、今回出てきた課題への打ち手を考え、解決に導くための取り組みも実行してきたいと思います。 最後に、LIFULL ではともに成長していける仲間を募集しています。よろしければこちらのページもご覧ください。 hrmos.co hrmos.co
こんにちは!LIFULLのエンジニアで、Ltech運営チームの河西です!今回は 2023年2月21日(火)に開催した『Ltech#23 LIFULLにおけるSalesforce活用事例について語ります』についてレポートします。 Ltechとは 株式会社LIFULL主催の、技術(エンジニアリング・テクノロジー)をテーマにしたイベントの総称です。 特定の技術に偏らず、様々な技術をピックアップしていきます。 Session1 Salesforceのシステム構成と最近の開発施策の共有 www.docswell.com このセッションでは、LIFULLにおけるSalesforceの利活用による目指す世界、そのために直近で行った施策について紹介いただきました。 最初に、Salesforceの利活用によって実現される世界として、「オムニチャネルの実現」を掲げ 一箇所にデータを集めて、オムニチャネルを実現。 LIFULLのエンドユーザ様へ最高のユーザ体験をご提供したい。 そのために、LIFULL HOME'S等LIFULLの各サービスや社内システムを繋ぎ、CRM(Customer Relationship Management)を実現する。という世界観を語っていただきました。 続いて、様々な具体的な取り組み事例として PIS(Personal Information System)というお問い合わせ情報を一元管理するためのAPIを開発 ログイン画面でユーザ登録した、ログインユーザ認証情報を格納・管理するための仕組みを構築 Salesforce Marketing Cloudと連携し、エンドユーザに対して、物件案内のメールを配信する仕組み 不動産会社様向けLIFULL HOME'S PROサイトで閲覧できるレポート機能 商談・注文情報など各種情報や売上金額が確認できる社内システム Pardotを利用した不動産会社様向けツールの利用 などなど、様々な事例をご紹介いただきました。 今回は時間の都合上、全てを細かく紹介できませんでしたが、まさしくCRMを実現するために、様々な取り組みをされている印象でした! Session2 Salesforce Field Service Lightningによる不動産相談窓口サイトの開発立上げ www.docswell.com このセッションでは、Field Service Lightningを利用して、不動産相談窓口サイトの立ち上げを行った話について紹介いただきました。 LIFULL HOME'S住まいの窓口の相談予約ページでは、高いNPS(Net Promoter Score)を実現するために、手動による管理が多くの工数を占めており、運用負荷が高い状態でした。 その状況を打開するために、Field Service Lightning(以下FSL)に着目し、 テクニカルナレッジは公式のわずかなものだけ 国内導入事例が皆無の新製品での挑戦 という状況下のなか、如何にして改善を行ったのかをご紹介いただきました。 当日の発表を聞きに来ていただいた方からも、FSLについてのQAが多く、 ・Field Service Lightning は使ったことがないのですが、導入にあたってハマったポイントや苦労した点はありますか? ・Field Service Lightningを選んだ理由はなんですか ・Field Service Lightningはチャット機能等、ほかにもいくつかありそうですが予約受付以外ではどのような機能をつかっていますか? といった様に、実例が少ない中、実際に導入・運用をされた経験を聞けた貴重なセッションでした! Session3 SalesforceのデータをもとにTableauで月ごとの売上金額を表示 www.docswell.com このセッションでは、最初のセッションで紹介されていた「商談・注文情報など各種情報や売上金額が確認できる社内システム」についての具体的なお話について紹介いただきました。 LIFULLにおける商談の流れの中で、それぞれ商品情報の持ち方が異なるため、月ごとの売上がいくらなのか集計しずらいといった課題がありました。 こちらの課題を解決するために、 SalesforceのApexバッチやApexトリガで売上金額を分割 BigQueryに連携 BigQueryに連携したデータをTableauで可視化 といった手法を用いて解決した事例を紹介いただきました。 QAでは、以下の様な質問もしていただき、 ・Salesforceの標準レポートやダッシュボードの機能とTableau?の機能に差はありますか? 回答として、「Salesforceで補えない部分を他のサービスを組み合わせて解決していく」といった、実務でないと聞けない貴重なお話を聞くことができました! まとめ 今回はLIFULLにおけるSalesforce活用事例としてSalesforceに関する話を3名のエンジニアに発表いただきました。この他にもLIFULL HOME'Sではメンバーが随時 LIFULL Creators Blog にて情報を発信しています。 www.lifull.blog Ltechでは、LIFULLのエンジニアが中心になって皆様の技術欲を満たすよう実例を交えた勉強会を開催しています。今後も Ltech を積極的に開催していきますので、ぜひ気になった方は、connpass で LIFULL のメンバー登録をよろしくお願いします! lifull.connpass.com また、LIFULLでは、数多くの職種の仲間を募集しています。 よろしければこちらのページもご覧ください。 【エンジニア】募集求人一覧 | 株式会社LIFULL 【エンジニア】カジュアル面談 | 株式会社LIFULL
プロダクトエンジニアリング部の二宮です。 我々のプロダクトエンジニアリング部では「強い個人・最高のチームになることで価値創造を加速させ続ける」というビジョンを掲げています。そして、その「強い個人」を目指して、週に数時間程度、普段できないチャレンジングな技術の探索など、ある程度自由に時間を使うことが推奨されています。 その一つのやり方として、最近は社内で技術書の輪読会をすることが流行ってます(以前、LIFULLクリエイターズブログにも「 "INSPIRED"の輪読会を通してふりかえるプロダクト開発 」という記事も共有されています)。 今回は、2つのチーム合同で『 システム運用アンチパターン 』を読み終わり、その輪読会がなかなか好感触だったので紹介します。ある程度ベテランのエンジニアが持つ知識を身につけるとともに、本の内容に触発された議論も同時に行えたと思っています。 輪読会とは まず、輪読会とはなにかに説明します。 weblio辞書 から引用します。 人々が集まって、同じ教科書などの本を読み、その内容について意見を交わすことを意味する語。 事前に決められた担当者が、本の内容を訳したりまとめたりしてから、他の参加者が理解できるように発表する形式がとられることも多い。 ちょっと話を先取りすると、個人で勉強するより「質問ができる」「その場で自分たちの文脈での議論ができる」などのメリットが感じられました。 輪読会の実施方法 輪読会には様々なやり方があるのですが、私たちが実際にどのように実施したのか紹介します。これ以外の方法を幅広く知りたい方は「 輪読会のすゝめ。全8回の開催で学んだ失敗パターンと成功のコツ 」などの記事が参考になると思います。 参加者 担当プロダクトが別の2つのチームが合同で行いました。人数は6人で、全員がソフトウェア開発がメインのエンジニアです。 本の選定 候補に挙がったのは次の3つの本です。 システム運用アンチパターン Googleのソフトウェアエンジニアリング 仕事ではじめる機械学習 「主管システムに関わらず共通しているシステム運用の実務に関して学べそうな内容で、比較的短期間で読み終わりそう」という理由で『システム運用アンチパターン』を選びました。 重厚な承認プロセス、可視化されていない運用、プロセスの最後でのみ行われるソフトウェアテスト、ノイズだらけのアラート、インシデントから学習しない習慣、時間外のデプロイ、情報のため込みなどを取り上げ、ソフトウェアシステムの開発運用が滞るチームや組織に共通してみられる陥りがちな状況や犯しがちな間違いをアンチパターンとして紹介します。そして管理職やマネージャでなく、エンジニアが実行し、繰り返すことで改善できる具体的な行動を解説します。 本の内容もけっこう面白く、後述する「過去の失敗談をフラットに共有できた」「開発文化について考える機会となった」みたいな感触は、この本のテーマのおかげが大きかったんじゃないかと思います。 実施方法 「各章の担当者を決め、毎週輪読会の時間を取り、1章ずつ担当者が内容をまとめて発表する」というオーソドックスな方法で行いました。輪読会本編は前半で発表を聞きながら質問やコメントを表に書いていき、後半でそれを元に話をする形式です。 第3章の「盲目状態での運用」で会話した跡の表 このように、「社内の文脈に置き換えるとどうなのか?」とか「実は本の内容と近い失敗をして後悔してるんだ」とか話が広がりました。 輪読会をやりながら、工夫して変えた点は2点あります。自分たちにとって輪読会ははじめての経験だったため、途中で一度振り返りの時間を用意していました。 輪読会の時間を15分に設定していたが、めちゃめちゃ駆け足になってしまったため30分に延長した まとめ方は完全に自由だったが、「どこまでまとめればよいかが分からなくて大変じゃない?」「自分の経験も絡めた話もあったほうが面白そうだ」みたいな声が上がり、簡単な推奨フォーマットを用意した フォーマットといっても、要約や章のポイントを箇条書きし、関連するエピソードや自分なりの解釈 をコメントするという簡単なものです。 実施した実感 輪読会の後に振り返りでは、次のようなメリットが感じられたという意見が出ました。 本の内容に触発され、ベテランの過去の経験を聞くことができた。過去の失敗談をフラットに共有できた 他の人に説明する必要があるので、担当した章の内容を、分かったつもりにならずに理解できた 社内の開発文化について自分の立場から貢献できることはないか考える機会となった 共通認識ができて、その場で現状改善のアイデアの議論ができた 会話が弾んだ。単純に楽しかった 特にこの本の内容はネガティブさとポジティブさのバランスが絶妙だったと思います。例えば「 第10章 ブレントだけが知っている 」には次のような話がありました。 意識しないとキーパーソン(『 The Phoenix Project 』の登場人物のブレント)に知識が集まる 情報を積極的に共有すればいい?→公開するだけでは興味を持てるわけではない ひどいと誰も全体を見なくなる 私自身もそうだったことがあるように、「せっかく情報共有のドキュメントを書いたのにみんなが興味を持ってくれない」「組織文化がドキュメントの重要度を理解してない」という、自分自身のモチベーションを下げ、冷静な議論を妨げてしまう形で悩んでしまうことも多いと思います。 ただ、そのような失敗例を共有するだけでなく、「実はドキュメントだけでなく別のコミュニケーションの方法もあったんじゃないか」とか「情報共有を習慣づけするためにこういう方法もあったんじゃないか」という紹介があり、そこでポジティブで建設的な話に自然に繋がったように思います。 おそらくDevOpsやアジャイル手法の本は、特にエンジニア経験の違いに関わらず発展的な議論ができ、同様の感触が得られるものも多いんじゃないかと思ってます。特にベテランから若手へと、数々の失敗で学んだ暗黙知を共有するのにも役立つかもしれません。 そして次の輪読会へ 今回の輪読会では、きちんと本を最後まで読み終わり、2チーム合同の輪読会の形では解散ということになりました。 次に、自分たちのチームでは『 仕事ではじめる機械学習 』を読み始めています。自分たちはBigQueryにあるデータを扱うことが多く、機械学習も絡めたシステムを作れれば、より有用な機能を実装するチャンスを広げられると考えているためです。今度は本の内容に合わせて「全員が軽く事前に読んでいて、それぞれが気づいた点や質問したい点をまとめて発表する」という別のやり方で工夫しています。 仕事ではじめる機械学習の輪読会の様子 こちらも、また機会があればブログで報告します。 最後に 最後に、募集求人やカジュアル面談のページを紹介します。一緒に成長しながら、前向きにチーム文化を作っていける方に来ていただけると嬉しいです🙇♂️ hrmos.co hrmos.co
こんにちは!LIFULLプロダクトエンジニアリング部の 鄭 在淳(ジョン・ジェスン) です。2022年に新卒で入社して、主に 不動産アーカイブ や 住まいインデックス の開発・運用を担当しています。 今年、新卒2年目のエンジニアとなり、ますます幅広い分野の業務に取り組んでいます。そして、自分が担当するタスクをより効率良くこなすためには、 個人の「情報力」を成長させることが非常に重要 だと感じています。 「情報力」とは、エンジニアが最新技術や良いコードの書き方、アーキテクチャ設計などの 情報を習得(Input) し、これらの情報を 実際の業務で活用(Output) する一連の流れと定義します。つまり、エンジニアたちの情報との向き合い方を意味します。 「情報力」を向上させるためには、自己学習などを通してエンジニア自身が一人で頑張れば、十分成長できるかもしれません。一人ではなく、 多くの人が集まって一緒にすれば、より大きな価値を出すこと ができます。 LIFULLではエンジニアの「情報力」向上のため、様々な取り組みを行っているので、今回の記事でいくつかの活動を紹介します。 目次 目次 LIFULLの活動紹介 Qiita Blog LIFULL Creators Blog LIFULL Developer Channel エンジニアいつでも相談 エンジニア向けの社外・社内イベント まとめ LIFULLの活動紹介 Qiita Blog 主にLIFULLのエンジニアたちが Qiita organizations にアカウントを登録して 誰でも自由に作成できる技術ブログ です。技術的な内容以外にも、プロジェクト運用・効率的なツールの使い方・開発環揃えなど様々なカテゴリーの記事を投稿しております。 Qiita Advent Calendarに参加し、LIFULLは全てのカテゴリーの中で7位となるほど大盛況でした。その中でも、 @pal4de が投稿した2件の正規表現式記事は、合計で500件を超えるいいねを獲得しました。正規表現でお困りの方は是非ご覧になってください。 たった4文字でコード検索の精度がブチあがる正規表現 シンプル図解: 正規表現の (?= ) とか (?! ) とか (?<= ) とか (?<! ) とか LIFULL Creators Blog この記事が掲載されているHatena blogです。LIFULLのビジョン実現につながる価値提供への取り組みを発信しております。 LIFULLのコーポレートメッセージ LIFULLのビジョン Qiitaとは異なり、エンジニアではなく「LIFULLのものつくり」に取り組んでいる社員なら、職種と関係なく記事を投稿できます。主にLIFULLのサービスを発展させるため、取り組んでいる内容が投稿されていて実際のプロダクトを事例としているので、 記事を通してLIFULLの文化や雰囲気などを知ること ができるのが特徴です。 例えば、LIFULLへ入社を考えている方が気になる「リモートワーク化での働き方やコミュニケーションの取り方」や リモートワーク化でも大切にするオフラインコミュニケーション リモートワーク時代におけるサークル活動の取り組み 「LIFULLのプロダクトどのようなシステムで運用されているのか?」等の入社前に知ることができない情報を記事を通して確認することができます。 LIFULLの全社アプリケーション実行基盤 KEEL について LIFULLのプロダクトの可観測性の向上について LIFULL Developer Channel 自分自身も運営メンバーとして参加している YouTubeチャンネル です。 LIFULLのエンジニアたちがYouTubeを通して、QiitaやCreators Blog 等のようにテキストに加え動画といった より多様な形式での情報の発信ができる環境を創る ために運営メンバーとして参加しています。 昨年9月頃に 「情報セキュリティ対策を行う意義」 という最初の映像を投稿させていただきました。3月上旬頃に2本目のLIFULLエンジニアのキーボードを紹介する動画を投稿することを目指しています。 LIFULLの文化や雰囲気をよりリアルで伝えていきたいと思いますのでよろしくお願いします。 エンジニアいつでも相談 1年ほど前にエンジニアの二宮が投稿したブログでも紹介させていただいた、GitHub Discussionsを使った社内向けのQ&Aフォーラムです。エンジニアが 誰でも気軽に技術相談やプロダクト仕様に関する質問など行えるようにすること を目的として作られたのが「エンジニアいつでも相談」です。 GitHub Discussionsで社内のQ&Aフォーラムを開設する 例えば、誰かが「設計の方針を決定することで〇〇が気になります。」、「実装で〇〇を迷っています。」、「〇〇に関して知見がある方がいらっしゃったら、教えていただけますか?」のような 質問を投げると、LIFULLエンジニアの皆が回答 してくれます。 このように相談しやすい環境ができているので、いつでも心理的安全性を保ちながら働くことができます。複数の人がDiscussions内で議論して解決策を探っていく様子がOSS活動にも似ていると感じており、課題に対して皆が協力して一緒に解決するという開発文化が社内で作られています。 エンジニア向けの社外・社内イベント 「カイゼン・ジャーニー」という書籍でも紹介されたことがありますが、 チームから会社へ越境して社内改善の場を作る のはエンジニアリングで非常に重要なところです。それを実現するため、LIFULLではLtech、LIFULL Tech Hub、ハンガーフライト、フリートーク勉強会等のエンジニア向けの多様な社外・社内イベントを開催しています。 LIFULL主催の技術勉強会 Ltech 『#21 LIFULL HOME’Sを支える検索技術』開催レポート (社外向け) 社内テックカンファレンスLIFULL Tech Hubを開催しました (社内向け) 毎月、技術的な話からチームのプロジェクト管理方法など様々なテーマでイベントが開催されており、自部署で担当している業務範囲以外の分野の技術・知識も得ることができます。経歴や担当業務に限らず、希望すれば誰でも手を挙げて発表できるので、小さな改善でも全社的に拡大していくことができます。私も入社して2回程度自分が改善のため取り組んだことを発表したことがあります。 まとめ 今回紹介した活動以外にもLIFULLでは エンジニアの情報力を成長させることができる様々な活動 をしています。こうした活動が「エンジニアとしてみんなを幸せにしたい」という想いの実現につながり、LIFULLの社是である「利他主義」とも繋がっていると思います。 LIFULLのエンジニア組織は エンジニアとして経営をリードする ことで活躍するというスローガンを掲げています。短期的に技術の幅を広げるだけでなく、技術を手段として中長期的に社会課題解決に貢献していくことを目指しています。 LIFULLではコーポレートメッセージである「あらゆるLIFEを、FULLに。」の実現を目指して、国籍、年齢に関係なく共に働いていただける仲間を募集しています。興味がある方は以下のページをご覧ください。 hrmos.co hrmos.co
エンジニアの松尾です。LIFULL HOME'S の売買領域を支えるエンジニアチームのマネジメントを担当しています。 私が所属する組織ではLIFULL HOME'Sからより良い価値を提供していくために、エンジニアの「業務効率化」と「コミュニケーション活性化」が課題となっています。今回はこれらを効率良く進めるために取り組んだ内容を紹介します。 組織の課題 業務効率化 コミュニケーション活性化 両立のための取り組み 開催の準備 コンペ当日の流れ その後の取り組み まとめ 組織の課題 業務効率化 プロダクトエンジニアリング部では、ユーザーへの価値をより早くより良く提供するために、常に業務プロセスの効率化を検討しています。 KPIマネジメント を元に、どのような作業がボトルネックになっているかを適宜洗い出しながら着実に進めていきます。 ボトルネックの分析から「データベースからのデータ取得業務(SQL作成)に割いている時間が長そう」という結果が見えており、削減を検討していました。 コミュニケーション活性化 LIFULLでは部署やチームの結束を高めるために「総会」という形での場作りを行っており、プロダクトエンジニアリング部2ユニットでも月に一度のユニット総会を開催しています。 リモートワーク中心での業務では直接会話する機会も少なくなっているため、グループを超えたコミュニケーションの活性化は組織の課題となっています。 両立のための取り組み そこで、(「業務効率化」につながる)SQLを作成するコンペを、(「コミュニケーション活性化」のために)ユニット総会の場で行うことにしました。 チームに分かれて、制限時間内に完成したSQLの数で競ってもらうことにします。 開催の準備 過去にあったデータ抽出の依頼やほかの職種のメンバーへのヒアリングを元に、「あれば今後の業務が楽になりそうなSQL」をイメージして作問しました。問題として成果物に期待される条件と、カラム名を与えるようにしています。 問題のサンプル 最終的に30問程度の問題を用意しましたが、すべての回答を用意するのは難しく(むしろ用意すると開催の意味がなくなるため)、正解は成果物の内容から軽いチェックで判断することにしました。※成果物のレビューについては後述します。 コンペ当日の流れ 開催が12月後半だったこともあり、グループを紅組と白組の2チームに分けて競ってもらう形式で実施しました。 参加者は人数が多かったため、チーム内でMeetでの部屋の分割やSlackのハドルを活用した分担を行いながら進めてくれていたようです。社歴でバランスを取ってペアを決めたり、「新築マンション関連は詳しいので任せてください」というような強みでチームをリードしたり、各チームで効率を考えながら取り組めていました。 開催の成果として多くのSQLができあがり、隣の部署のメンバーとの会話の機会も作れたことで、当初の目的は達成できたと感じています。 その後の取り組み さまざまなデータを取得できるようにはなりましたが、「なぜこのテーブルから取得するのか」「なぜこの条件を絞るのか」という疑問が解消しきれていない箇所もあります。 そのため週に一度有志のメンバーが集まり、完成したSQLを一つずつ紐解きながらLIFULL HOME'Sの知識を蓄積していく勉強会を行っています。この会はレビューも兼ねており、これにより正確にデータを抽出できるしくみが整ってきています。 まとめ SQL作成のコンペを通して、「業務効率化」と「コミュニケーション活性化」の両立に取り組んだ事例について紹介しました。今後もより良くユーザーへの価値提供を行っていくために、無駄を省き本質に集中できるしくみを作っていきたいと思います。 最後に、LIFULL ではともに成長していける仲間を募集しています。よろしければこちらのページもご覧ください。 hrmos.co hrmos.co