一休.com Developers Blog

一休のエンジニア、デザイナー、ディレクターが情報を発信していきます

「一休×AEON 事業会社のサービスを支える基盤開発トーク」を開催しました

一休×AEONイベントの様子

はじめに

kymmtです。

先日2024年9月18日に、「事業会社のサービスを支える基盤開発トーク」と題してイオンスマートテクノロジー(以下AST)さんと合同で技術イベントを実施しました。

ikyu.connpass.com

イベントでは、各会社の事業を支える基盤プロダクトの開発や運用における苦労や工夫について登壇者の方々にお話しいただきました。

この記事では、このイベントの様子や発表の内容を紹介します。なお、X(旧Twitter)でも#ikyu_aeonというハッシュタグで当日の様子がご覧になれます。

会場

会場は、一休のオフィスも入っている東京ガーデンテラス紀尾井町内のLODGEでした。

当日は、一休/ASTのメンバーも合わせて計30人程度の方にご来場いただきました。また、イベント開始前に、ASTのもりはやさんからトップバリュ製品やイオンで販売中のお菓子を来場者向けに提供していただきました。

発表

『歴史あるプロダクトにマイクロサービスを導入するプロセス』

1つ目の発表は、一休の菊地さんによる『歴史あるプロダクトにマイクロサービスを導入するプロセス』でした。

一休のプロダクトを横断して利用されるマイクロサービス群(社内では一休プラットフォームと呼んでいます)を開発するチームでは、個別のプロダクトへのマイクロサービス導入も進めています。長い歴史を持ちコードベースが複雑なプロダクトにマイクロサービスを導入するには、技術課題の解決にとどまらず、積み重なった仕様を解きほぐして関係者と調整を進める必要もあります。

この発表では、そのような課題に直面した一休.comレストランへのポイント管理マイクロサービス導入の事例を紹介いただきました。発表のなかで、デッドコード削除や仕様の調整のような地道な取り組みから、プロダクトとマイクロサービスを疎結合に保ちつつ連携する仕組みを解説していただきました。

『1000万DLを超えたiAEONアプリ:完全停止を防ぐ耐障害性と信頼性の設計』

2つ目の発表は、ASTの范さんによる『1000万DLを超えたiAEONアプリ:完全停止を防ぐ耐障害性と信頼性の設計』でした。

iAEONアプリは実店舗のレジ前で会員バーコードを表示するようなユースケースを想定しており、障害が発生して利用不可になることを可能な限り避けたいという要件があります。一方で、複雑なバックエンド側の一部で発生した障害がアプリに伝播することで、アプリが利用不可になることも過去あったとのことでした。

この発表では、上述したような特性を持つiAEONアプリの耐障害性を高めるための取り組みについてお話しいただきました。とくに、デバイス上のキャッシュなどを活用してフロントエンドであるiAEONアプリ上のエラーをできるだけ局所化する手法について詳しく解説いただきました。App StoreやGoogle Play StoreにおけるiAEONアプリの評価が結果的に向上したとのことで素晴らしいと感じました。

『宿泊予約サイトにおける検索と料金計算の両立』

3つ目の発表は、一休の鍛治さんから『宿泊予約サイトにおける検索と料金計算の両立』でした。

宿泊予約サイトである一休.comやYahoo!トラベルでの料金に関する業務ルールは複雑です。また、ユーザーが宿泊したい部屋をさまざまな条件に基づいて検索するときに、その複雑な業務ルールで算出される料金の検索サーバであるSolrで計算する必要があります。

この発表では、そのような一休.comの検索要件の複雑さの解説や、要件を満たすためにSolrのプラグイン機構を活用していることについて解説いただきました。SolrのプラグインはJavaで開発することができ、Javaの機能を活用できるので、Solrクエリをメンテナブルに保ちつつ、複雑な料金計算を検索時に実行できているとのことでした。

『SRE改善サイクルはチームを超えて - ダッシュボードを眺める会の取り組み』

4つ目の発表は、ASTのもりはやさんから『SRE改善サイクルはチームを超えて - ダッシュボードを眺める会の取り組み』でした。

New Relicなどを活用したシステムメトリクスを概観できるダッシュボードは、非常時に障害の原因を探るためのものとして非常に便利です。一方で、定点観測することで、日々のシステムの状態や、障害になり得る変化を見つけることができます。

この発表では、ASTのSREチームを中心にダッシュボードを定期的に眺める会を設けることで、メトリクスの変化や改善ポイントを発見して深掘りする機会を意図的に作り出す取り組みについてお話しいただきました。システムの信頼性を高める機会を作り出すのはもちろん、会を通じて「ザイオンス効果(単純接触効果)」でチームビルディングにも寄与している点が素晴らしいと感じました。

おわりに

「事業会社のサービスを支える基盤開発トーク」の様子について紹介しました。

各社のサービスの基盤プロダクト開発について社内外のエンジニアの工夫や知見が聞ける、とてもおもしろいイベントになりました。ご来場いただいたみなさま、ありがとうございました!


一休では、ともに良いサービスをつくっていく仲間を募集中です。

hrmos.co

カジュアル面談も実施しているので、お気軽にご応募ください。

www.ikyu.co.jp

情シスカンファレンス「Business Technology Conference Japan 2024」にブロンズスポンサーとして協賛します

コーポレート本部 社内情報システム部 兼 CISO室 id:rotom です。

10/12(土) にハイブリッド形式で情シス向けのテックカンファレンス「Business Technology Conference Japan 2024(BTCONJP 2024)」が開催されます。

btcon.jp

btajp.connpass.com

昨年オンライン開催された BTCONJP 2023 では私が登壇者として 本社を東京ガーデンテラス紀尾井町へ移転し、オフィスファシリティ・コーポレートIT を刷新した話 というテーマで発表させていただきましたが、今年は core staff として運営に参画しており、所属企業である一休はブロンズスポンサーとして協賛しております。

Identity, DX & AI, Device Management, Zero Trust, Cyber Security, Business Technology の6つのテーマに沿った12のセッションや、イオン / イオンスマートテクノロジー CTO の 山﨑 賢氏による基調講演を用意しています。 詳細は以下のプレスリリースをご覧ください。

prtimes.jp

オフライン会場は一休 本社も入居する、東京ガーデンテラス紀尾井町 紀尾井タワーのLINEヤフー株式会社 本社です。

map.yahoo.co.jp

LODGE での懇親会も予定しておりますので、ぜひ現地でご参加ください!

プロンプトエンジニアリングをしよう - 一休.comでの検索システム改善事例

はじめに

こんにちは。宿泊プロダクト開発部の宮崎です。

みなさん、生成 AI 使ってますか?

近年、AI の進歩はめざましく、文章生成や画像生成はもちろん、動画生成も実用的なレベルで出来るようになっています。

ChatGPT が話題になったのが 2022 年の 11 月なので、たった 2 年足らずでここまで来ているという事実に少し恐ろしくもありますね。AGI(汎用人工知能)の実現もそう遠くないのかもしれません。

一休でも AI 技術は注目していて今年の 6 月に、まさに生成 AI を使ってホテル検索システムの改善を行いました。

この記事では、その時に学んだプロンプトエンジニアリングの重要性について書いていこうと思います。

生成 AI を使ったホテル検索システム

今回我々が実装したのはフリーワード・文章でもホテルを検索できるシステムです。

以下のようなユーザーの自由な入力に対して、適切なホテル・旅館を返したいというのが目的でした。

  • 福井でおいしいご飯が食べられる宿
  • 沖縄 子供と楽しめる宿
  • 静岡で犬と泊まれる宿

今までは、このような入力の場合、形態素解析をして検索を行っていました。しかしその場合、「子供と楽しめる」だと「子供」「楽しめる」に分割して検索するので、本来の意味「子供と楽しめる」とは少し結果が違っていました。

よって文章の入力に対しては意味を考慮して検索ワードを切り出す必要があります。

私たちが行ったのは、AI にユーザーの入力を解析させ意味毎に区切り、検索条件 area, condition に分解させるというものです。以下に具体的な例を示します。

例: ユーザーの入力:「銀座の夜景が楽しめる」

↓ これを AI で解析して分解する。

求める出力: { area:銀座, condition:[夜景が人気] }

従来は「銀座」「夜景」「楽しめる」で分解されていたのが、「銀座」「夜景が人気」に分解する。 このようにして json 形式で返してくれれば、既存のシステムで検索できます。この分解を生成 AI にやってもらおうと考えました。

実際の検索結果

具体的にどんな検索になったのか、実際にリリースしたものを使ってみましょう。

まず、行きたい施設について文章を入力し、検索ボタンを押す。

今回は「東京近郊でサウナがあって禁煙」と入力してみました。

以下の結果が表示されます。 東京近郊の都市で、サウナが人気、そして禁煙で検索されていますね。 このように、ユーザーの入力ワードをシステムで検索できるよう AI で分解するというのが今回行った改善です。

実装における課題

ただ、この仕組みを実装する上で、1 つ大きな課題を抱えていました。

それは単純な話で、コストの問題です。

当時、私たちはこの分解に GPT-4 を使っていました。 理由は他の AI と比較して GPT-4 が一番結果が良かったからです。(このプロジェクトは去年の秋ごろに始まったため、選択肢があまりなかったというのもあります。)

しかし、GPT-4 だとコストが高く、1 回の検索に 10 円以上かかることが分かりました。

どうしてそれほどコストがかかるのかというと、プロンプトが長いからです。

一休では、例えば近畿というエリアは「近畿(大阪以外)」と「大阪」という風に分けられています。 このような一休独自のエリアの分け方や、用語を AI が解釈できるようにプロンプトに詰め込んでいるので、どうしてもその分プロンプトが長くなってしまうのです。

プロンプト例:

扱うエリア名は以下です。
- 北海道
  - 札幌
  - 函館・湯の川・大沼
  - 旭川・富良野・稚内
  - ...
  - ...

<<以下、地名がずらりと後に続く…>>

解決案

GPT-4 ではコストがかかる。プロンプトを短くするのも難しい。 そこで考えたのは、GPT-3.5 Turbo を使うことでした。 これを使えば GPT-4 の 1/60 の値段になるので、コストの問題は簡単に解決できます。

ただし、これが最初からできていれば苦労はしません。

例えば「大阪でサウナと温泉が楽しめる」なら、GPT-4 は

{ area:大阪, condition:[サウナ,温泉] }

と出力されるのに対して、GPT-3.5 Turbo は以下の様に間違うことが多かったです。

  1. いくつかのキーワードが欠けている

    例:{area: 大阪,condition: [サウナ] }

  2. 入力がそのまま入ってしまっている

    例:{area: 大阪,condition: [サウナと温泉が楽しめる] }

こういった間違いに対して、最初はファインチューニングで精度を上げようとしました。 ファインチューニングは既存のモデルに追加でデータを学習させて、微調整するというものです。

参考:https://platform.openai.com/docs/guides/fine-tuning

しかし、これも上手くいきませんでした。

例えば condition の解釈精度をチューニングすると area 解釈精度が悪化したり、逆もまた然りであちらをたてればこちらがたたず状態に…。

結果的にプロンプトを 2 つに分けて area 用と condition 用、のようにしてみましたが、精度の割にはコストが 2 倍に増えてしまって断念しました。

※補足:精度の検証には新しくデータセットを作成しました。入力キーワードと、どのように分解して欲しいかの回答のセットです。これらを用いて生成された回答の一致率を測定しています。

プロンプトエンジニアリングをしよう

頼みの綱のファインチューニングもうまくいかず、頭を悩ませていた時のことです。

私は OpenAI 社のファインチューニングのドキュメントを読んでいました。チューニング精度を上げるための秘訣が書かれていればと思ったのです。

するとその時、以下の一文が目に留まりました。

Fine-tuning OpenAI text generation models can make them better for specific applications, but it requires a careful investment of time and effort. We recommend first attempting to get good results with prompt engineering, prompt chaining (breaking complex tasks into multiple prompts), and function calling,

引用:Fine-tuning (https://platform.openai.com/docs/guides/fine-tuning/fine-tuning)

簡単に言うと、ファインチューニングの前にまずはプロンプトエンジニアリングやプロンプトチェイニング(タスクを複数に分割する)をしましょう、ということです。

私はこの時まで、プロンプトエンジニアリングを軽視していました。プロンプトの修正で出力が改善されれば苦労しないだろうと。

ですが、このドキュメントを見ながら自分の今のプロンプトを見返すと、推奨されている書き方をほとんどしていないことが分かりました。

よって、半信半疑でありながらも、とりあえずドキュメントに従ってプロンプトエンジニアリングを行いました。

すると驚くべきことに、GPT-3.5 Turbo でも GPT-4 と同等の精度を出すことができたのです。

難しいことは何もしていません。ただ、プロンプトを修正しただけです。

それだけでコストが 1/60 になり、今年の 6 月にこの機能をリリースすることができました。 まず最初にやるべきはプロンプトエンジニアリングだったというわけです。

※補足:現在は GPT-3.5 Turbo ではなく、 GPT-4o mini を使っています。

プロンプトエンジニアリングについて

ここからは具体的にどういったプロンプトをどう修正したのかについて書きます。

OpenAI のプロンプトエンジニアリングのガイドラインを参考に以下の修正を行いました。 参考:https://platform.openai.com/docs/guides/prompt-engineering

はっきりと簡潔な指示を出す


簡潔な言葉で何をしてほしいかを指示しました。

★ 修正前のプロンプト

現在、日本のホテルを検索するシステムを開発しています。システムは以下の機能を持っています。

<<システムの説明 ※ここでは省略。実際は 50 行くらい使ってホテルや宿泊条件など、機能の詳細な説明をしていた。>>

ここで、以下のユーザーのホテル検索クエリに対して、上記の機能を使って絞り込むのが適切だと判断したのなら、その条件を教えてください。

★ 修正後のプロンプト

あなたは優秀なクエリ分析システムです。
ユーザーのホテル検索クエリが与えられますので、それを分析して、どんな条件で検索すればいいのかをjson形式で回答してください。回答には、三重引用符で提供されたデータのみを使って答えてください。

このヒントは以下に書かれていました。 https://platform.openai.com/docs/guides/prompt-engineering/tactic-include-details-in-your-query-to-get-more-relevant-answers

ステップバイステップで考えさせる


以前は 1 つの指示+複数のルールで指示していましたが、これをステップバイステップの指示に切り替えました。

★ 修正前のプロンプト

ここで、以下のユーザーのホテル検索クエリに対して、上記の機能を使って絞り込むのが適切だと判断したのなら、その条件を教えてください。
その際、以下のルールを守ってください。

1. JSON形式で教えてください。
2. たとえば、ユーザーのホテル検索クエリ「ペットと泊まれる 新潟」の場合、
  {area: ["新潟"], condition: ["ペット"]}
  というJSONを期待します。
3. ...
4. ...

★ 修正後のプロンプト

以下の思考フローを用いて、ステップバイステップで絞り込んでいくことを想定してください。
ステップ1:ユーザーのクエリを確認し、エリアに該当するものを抽出してください。
ステップ2:ステップ1で抽出したワードを出力のareaのキーに追加してください。
ステップ3:...
ステップ4:...

このヒントは以下に書かれていました。 https://platform.openai.com/docs/guides/prompt-engineering/tactic-specify-the-steps-required-to-complete-a-task

セクションを区別する


エリア名称や、用語一覧を渡しているのですが、ここを引用符などで区切りました。

★ 修正前のプロンプト

以下にシステムで扱える用語一覧を示します。
* サウナ
* 禁煙
* 喫煙
* 室内プール
* ...
* ...

★ 修正後のプロンプト

以下にシステムで扱える用語一覧を示します。
"""
* サウナ
* 禁煙
* 喫煙
* 室内プール
* ...
* ...
"""

このヒントは以下に書かれていました。 https://platform.openai.com/docs/guides/prompt-engineering/tactic-use-delimiters-to-clearly-indicate-distinct-parts-of-the-input

例を付ける


出力の例を付けました。上述したように、以前はルールを使って回答を制御していて、1 つか 2 つしか例を付けていませんでした。

それを以下の様に例を増やしました。

★ 修正後のプロンプト

以下は、出力のjsonの例です。

例1:「絶景と温泉」というユーザーのクエリの場合、以下の条件を出力してください。
{ condition : ["絶景","温泉"] }

例2:「浜松でうなぎ料理を楽しめる旅館」というユーザーのクエリの場合、以下の条件を出力してください。
{ area:["浜松"] condition: ["うなぎ料理"] }

例3:...

例4:...

このヒントは以下に書かれていました。 https://platform.openai.com/docs/guides/prompt-engineering/tactic-provide-examples

以上がメインとなるプロンプトの修正です。これらは本当にガイドラインに従って足りていないものを書き換えただけです。

それだけで約 35% の精度改善となったので、同じような悩みを抱えている方はぜひ試していただきたいです。

おわりに

今回、プロンプトエンジニアリングの効果を十分に理解することができました。

ただ、考えてみれば、人が人に仕事を任せる時は当然相手の立場やスキルを考えて指示を出します。 これをどうして AI でやらないのか。 AI も AI の理解しやすい命令の構造があり、それをプロンプトエンジニアリングで最適化する。

人の気持ちを考えるように AI の気持ちを考える。

いい仕事をするためには人も、 AI も関係なく、相手を思い遣る心が大切なのだと思いました。

オフライン技術勉強会「事業会社のサービスを支える基盤開発トーク」を開催します!

CTO室プラットフォーム開発チームの山口(@igayamaguchi)です。

この度、一休とイオンスマートテクノロジー合同で技術勉強会「事業会社のサービスを支える基盤開発トーク」を開催します! ikyu.connpass.com

このイベントでは

両社のシステムを支える基盤の開発についてお話しします。

様々なお話をしていただく予定ですが、一休から1つ「歴史あるプロダクトにマイクロサービスを導入するプロセス」について紹介します。
この発表では一休.comレストランにマイクロサービスを導入したときの取り組みについてお話しします。一休.comレストランはWebサービスとして18年もの歴史があるサービスです。歴史の長いサービスになると全てが新しい技術でできているわけではなくレガシーなアーキテクチャのものもあります。それらを考慮しながらマイクロサービスを導入していった泥臭い取り組みについてお話しする予定です。

他にも以下のようなトークを予定しています。

  • 宿泊予約サイトにおける料金計算の格闘
  • 1000万DLを超えたiAEONアプリ:完全停止を防ぐ耐障害性と信頼性の設計
  • SRE改善サイクルはチームを超えて - ダッシュボードを眺める会の取り組み

それぞれの開発で取り組んでいる課題についてリアルな話をお送りします。どのトークもとても面白い内容になると思います!

そして今回はオフラインで開催します。場所は一休本社も入居する東京ガーデンテラス紀尾井町17階にあるLODGEです。 https://www.z-lodge.com/www.z-lodge.com

懇親会もありますので、ご来場いただいた方はぜひ登壇者や他の参加者の方と交流していただければと思います。
ぜひお越しください!

React / Remix への依存を最小にするフロントエンド設計

CTO 室の恩田(@takashi_onda)です。

一休レストランのフロントエンドアーキテクトを担当しています。

Intro

一休レストランでは、以前ご紹介したようにフロントエンドで React / Remix を利用しています。

user-first.ikyu.co.jp

一方、設計方針としては、React / Remix への依存が最小になるように心掛けています。

今日は、そんな一見矛盾するような設計方針について、ご紹介したいと思います。

この記事を読んでいただき Remix に興味をもたれたら、明後日 2024/8/7(水) 19:00〜 のオンラインイベント

offers-jp.connpass.com

にもご参加いただけると嬉しいです。 この記事でご紹介している疎結合なフロントエンドアーキテクチャを実現する Remix の魅力についてお話します。

なぜ依存を最小にするのか?

React / Remix を使っていて依存しないってどういうこと?と疑問を持たれる方も多いでしょう。 まずはその動機からご説明します。

フレームワークやライブラリより寿命が長いプロダクトは珍しくありません。 栄枯盛衰の激しいフロントエンドでは、そういったサービスの方がむしろ多いのではないか、とも感じます。

一休レストランのサービス開始は2006年です。 同じ2006年に jQuery 1.0 がリリースされました。 まだ、フロントエンドという言葉が生まれる前の時代です。

一休レストランは、そんな時代から二度のリニューアルを経ながら(今は二度目の真っ最中)継続しているサービスです。 これからも広く使っていただけるよう日々、開発を進めています。

したがって、将来、エコシステムが大きく変わったとしても、その変化に少ない労力で追随し続けられることが重要となります。

フロントエンド領域も成熟してきているので、今後は、エコシステムが激しく入れ替わるような状況はもう訪れないかもしれません。 それでも、フレームワークやライブラリレベルでみると、メジャーバージョンアップは数年単位で見れば避けられず1、その中には破壊的変更を伴うものもあるでしょう。

バックエンド設計に倣う

バックエンド設計では、フレームワークへの依存を最小化する、という考え方が古くからあります。

すなわち、バックエンドの世界では、指針となる原則や、依存を最小にして疎結合にする技術が確立しているのです。

偉大な先人達の肩の上に乗るため、その知見はどういったものなのかを確認したいと思います。

依存性逆転の原則 (Dependency Inversion Principle)

ボブおじさんこと Robert C. Martin が提唱した SOLID 原則をご存知の方は多いと思います。その SOLID 原則の D 、依存性逆転の原則がフレームワークへの依存を最小化するための根幹の考え方になります。

(少々長くなるので、ご存知の方は読み飛ばしてください)

簡潔に説明すると、

  • 高レベルモジュールであるドメイン層が自身の必要とする抽象 (interface) を定義し
  • 低レベルモジュールにあたるインフラ層がその抽象を実現する詳細 (class) を実装する

ように設計すべし、という原則です。

高レベルモジュールが低レベルモジュールに直接依存するのではなく、低レベルモジュールが、高レベルモジュールの要求しているインターフェースの実装を提供する。 言い換えると、低レベルモジュールが高レベルモジュールの抽象に依存することから、依存性逆転の原則と呼ばれます。

少し雑に言えば、高レベルモジュールにあたるのが我々の開発するプロダクトです。 低レベルモジュールがフレームワークやライブラリと、それらを使ったインフラ層に相当します。

よく用いられる Repository の例で説明します。

プロダクトが知っているのは自身で定義した Repository の interface のみです。 プロダクトが Repository の実装を構成するライブラリやフレームワークの API を直接呼ぶことはありません。 Repository の interface もフレームワークが要求する interface から独立しています。

フレームワークへの依存が疎結合になりました。

腐敗防止層 (Anti Corruption Layer)

他にもバックエンドで培われた依存を最小化するテクニックとして、腐敗防止層は欠かせません。

DIP に比べると、シンプルでわかりやすいと思います。

ライブラリや外部のサービスを利用するときに wrapper を挟み、変更の影響をその wrapper に閉じこめるという手法です。 インターフェースや実装が安定しなかったり、将来交換する可能性が考えられるような場合に、特に有効です。

フロントエンドにどう適用するか?

「余計なことをしない」素直なフレームワークが大前提

現代のフロントエンド開発では、(メタ)フレームワークを利用することが一般的です。

まず、フレームワークに求められる要件を考えたいと思います。

「余計なことをしない」とは?

逆を考えるとわかりやすいかもしれません。

全部面倒を見てくれる、手厚いけれど、複雑な規約があり、その裏側がどうなっているかわからないフレームワークを思い浮かべましょう。フロントエンド・バックエンドは問いません。過去を振り返れば、だいたいどの言語にも一つはありそうです。

このような全部入りフレームワークは、

  • そのフレームワークが想定しているユースケースの範疇でコードを書けていて、
  • 運用面でも安定しているのであれば、

とても優れた開発効率や開発体験が得られるでしょう。

ですが、フレームワークが用意してくれているレールから外れないと実現が難しい要件は往々にして存在します。 そんな要件に遭遇してしまうと、フレームワークそのものに手を入れる以外の回避策しか見つからないことが多く、詰みます。2

また、そんな要件に出会わなかったとしても、そのフレームワークに密結合状態で依存しているだけで弊害は存在します。 たとえばメジャーバージョンアップで破壊的な変更が加えられたとき、その変更に追随するための苦労は過去にそのようなフレームワークを使ったことがある方なら想像に難くないと思います。

Remix の採用

さて、逆の状況を踏まえた上で、あらためてフロントエンドの世界で「余計なことをしない」フレームワークの条件を考えてみましょう。

標準 API の尊重、ブラックボックスがない、なだらかなアップデートパス、実装がシンプル、といった条件が挙げられます。

現時点において React ベースでは Remix が条件を最も満たしていると判断し、以前ご紹介したように、一休レストランでは Remix に乗り換えることを決断しました。

その上でバックエンド設計の原則に従い Remix API への依存は最小限になるよう努めています。

疎結合なアーキテクチャを実現するためには、逆説的ではありますが、フレームワークがそれを可能とする作りになっていることが重要なのです。

Remix だと、なぜそれが可能になるのかは、最初にご紹介したオンラインイベントでもお話する予定です。

React 非依存の Vanilla JS だけで使えるライブラリを選ぶ

一休レストランでは以前ご紹介した XState に加えて JotaiTanStack Query を利用しています。

いずれも React に依存していないという共通点を持ちます。

TanStack シリーズは Vanilla JS のコアと各フレームワークへのアダプタで構成されています。

Jotai は TanStack シリーズのようにフレームワーク独立を謳っているわけではなく、React で使うことを前提とした状態管理ライブラリですが、公式サイトにも

Now with a store interface that can be used outside of React.

とあるように v2 からは、Vanilla JS で利用できる状態管理ライブラリとしての側面も持つようになりました。

コアの Vanilla JS 部分と React アダプタが別れているため、他のフレームワークと組み合わせて使うことが可能です。 たとえば VueSvelte, SolidJS のアダプタを作っている方もいるようです。

React / Remix での DIP

具体例として、一休レストランの soft navigation 機能をご紹介します。

一休レストランでの soft navigation では Remix の useLocationuseNavigate を直接使っていません。

アプリ側で、

  • useLocation に対応する useNavigationContext
  • useNavigate に対応する useEventNavigate

というカスタムフックをそれぞれ定義しています。

DIP の観点から見ると、useNavigationContext, useEventNavigate の signature が、高レベルモジュールの定義する抽象に相当します。

具体的に見てみましょう。

export function useNavigationContext(): NavigationContext {
    // implementation
}

関数が first-class citizen なので signature (interface) さえ変わらなければ、

type UseNavigationContext = () => NavigationContext
export const useNavigationContext: UseNavigationContext = createUseNavigationContext()

極端な例ですが、呼び出し元のコードを変えずに、後から実装を動的に差し替える形にすることも可能です。3

さて、これらのフックは Remix の useLocationuseNavigate に加え Jotai, XState を利用して実装しています。 このフックの実装自体が、DIP における低レベルモジュールが実装する詳細にあたります。

もちろん、アプリで定義しているこれらのフックは、単に DIP を実現するためだけに導入しているわけではありません。 あくまで、サービス固有のユースケースを実現するための機能を付加した抽象層になっています。4

ユースケースを具体的に見てみましょう。

ユーザーが一休レストランで予約をするとき、人数日時などの予約条件や空席状況に応じて、次に表示するステップを切り替えたい場面があります。 このステップ、すなわち遷移先の切り替えは、固定的なナビゲーションではなかなか実現が難しい機能です。

また、レストランの空席状況は刻々と変化するので、その時点の状況に応じた動的な画面遷移が必要となります。

このようなユースケースに対応するため、ナビゲーションロジックは XState を使ったステートマシンで定義しています。 そして、ステートマシンが次の操作に相当するイベントをもとに次の画面(状態遷移)を決定する仕組みを取りました。

useNavigationContext はステートマシンの現在のステートとそのコンテキストを返し、useEventNavigate はステートマシンにイベントを送信する関数を返しています。

コンポーネント設計

最後に、フロントエンドのアーキテクチャにおいて、本丸となるコンポーネントの設計について説明します。

コンポーネント、カスタムフック、Vanilla JS ロジックの三層で構成しています。

コンポーネント

コンポーネントは表示だけの責務を担う、テンプレートエンジン的な位置付けです。

function CourseFilter() {
  const facets = useAvailableFacets()
  return (
    <div>
      {facets.map((facet) => (
        <FacetButton key={facet.key} facet={facet} />
      ))}
    </div>
  )
}

function FacetButton({facet}: {facet: Facet}) {
  const toggle = useToggleFacet()
  const onClick = useCallback((_: MouseEvent<HTMLButtonElement>) => {
   toggle(facet)
  }, [toggle, facet])
  return (
   <button type="button" aria-pressed={facet.selected} onClick={onClick}>
     {facet.label}
   </button>
  )
}

基本的に、フックで取得した値を表示したり、イベントハンドラにバインドしている以上の仕事はしていません。

カスタムフック

カスタムフックは Vanilla JS ロジックとコンポーネントを繋ぐアダプター層です。

function useAvailableFacets() {
  return useAtomValue(availableFacetsAtom)
}

function useToggleFacet() {
  const set = useSetAtom(toggleFacetAtom)
  return useCallback((facet: Facet) => {
     set(facet)
  }, [set])
}

Jotai の atom と接続するだけの薄いアダプターになります。5

Vanilla JS ロジック

Jotai の atom から先が、Vanilla JS (TypeScript) で書かれたロジックです。

ただの TypeScript コードなので、可搬性が保証されます。

自動テスト

自動テストは、単体テストと e2e テストのみでカバーしています。

単体テストでは React Testing Library を一切使用していません。 このことからも、React への依存が最小限になっていることが伝わるかと思います。

Vanilla JS ロジックは、そのほとんどを純粋関数として実装しているので、複雑な fixture のセットアップも不要で vitest で高速にテストが可能です。

依存の最小化で得られる利点

確実に発生するシナリオとして、フレームワークのメジャーバージョンアップに伴う破壊的な変更の影響を受けにくくなる、という点が挙げられます。

React 19 や React Router v7 (fka Remix v3) でどう変わる?

現時点で判明している範囲からの判断ではありますが、影響はほぼゼロになるだろうと見ています。

直接 Remix API を呼んでいる箇所は、これまで見てきたように DIP の低レベルモジュールにあたるフックの実装内に閉じています。 また、その構造上、Remix API の呼び出し箇所も最小限に抑えられているため、仮に変更が必要になっても、手を入れないといけない箇所は必然的に最小限に留められます。

加えて Remix 自体もその設計哲学で、メジャーバージョンアップで導入される機能や変更は future flag として段階的に適用できる形で提供されます。 破壊的な変更は伴うとはいえ、バージョンアップに追随する負担が抑えられたフレームワークと言えるでしょう。

例えば Server Component もオプトイン的に必要な箇所にだけ適用できるような仕様が検討されています。

React 19 や React Router v7 についても前述したオンラインイベントでお話しする予定ですので、興味のある方はぜひご参加ください。

極端な例だが、仮に他のフレームワークに置き換えないといけなくなったら?

コンポーネント設計でお伝えしたように、薄いコンポーネント層を移植するだけで対応できます。

TypeScript で書かれたロジックは、Vanilla JS というその性質上、変更することなくそのまま使えることには説明の必要もないでしょう。

Outro

依存ライブラリやフレームワークのメジャーバージョンアップ程度では、ほとんど揺らがないアーキテクチャができました。

あらためて前提を振り返ってみると、長い歴史を持ち、継続可能性が極めて高いサービスだからこその選択であるとも言えます。 スタートアップで、MVP でとにかく試行錯誤を高速に繰り返したい、といった状況下では、また別の選択肢があると思います。

かなり長くなってしまいましたが、ここまで読んでいただきありがとうございました。 この記事が、フロントエンドのアーキテクチャを考える上での一助となれば幸いです。


一休では、本記事でお伝えしたような課題をともに解決するフロントエンドエンジニアを募集しています。

www.ikyu.co.jp

まずはカジュアル面談からお気軽にご応募ください!

hrmos.co


  1. React 19 や React Router v7 のリリースが近づいています。
  2. Remix への移行を決めた理由の一つです
  3. 実際には素直に関数として実装しています。事前に定義しなくても関数の signature が interface として機能することを示すための例です。
  4. 実を言うと、最初から現在の設計に辿りつけていたわけではありません。当初は Remix の nested routes を駆使する案を検討していました。その過程でチームメンバーから示唆をもらい、ステートマシンを使ったアプローチに切り替えました。もし、当初案のままであれば DIP と正反対の状態になっていたと思います。
  5. Jotai のようなライブラリを利用しない場合は useSyncExternalStore を使って、ロジックを React と疎結合にできます。

エンジニア主導でデザインシステムを導入してみた

レストランプロダクト開発部の矢澤です。

一休では「RESZAIKO」というプロダクトの開発を行っています。 この開発を進めるにあたり、UI/UX に関するいくつかの課題があり、エンジニア主導でデザインシステムを構築することにしました。

本記事では、エンジニア主導でデザインシステムを構築することになった背景や、実際に取り組んだ内容について赤裸々にお話しします。

デザインシステムの導入を検討しているものの、最初の一歩を踏み出せずにいる・あるいは何から始めればよいかわからないチームにとって参考になれば幸いです。

そもそも RESZAIKO とは

RESZAIKO は飲食店の予約管理を DX する SaaS 事業で、現在3つのプロダクトを提供しています。

  • 複数予約サイトの在庫を一括管理する「サイトコントローラー」
  • 予約や顧客情報を管理する「予約台帳」
  • 店舗独自の予約ページを提供する「Web予約」

現在は3つのプロダクトがありますが、元々はサイトコントローラーだけを提供しており、予約台帳とWeb予約は後発のプロダクトとしてリリースしました。

デザインシステム作成の背景

後発プロダクトの開発を進めていく中での課題

私たちはサイトコントローラーがある状態で、「予約台帳」と「Web予約」の開発に着手しました。 同時進行で開発することになったこの2つの後発プロダクトは、既存プロダクトであるサイトコントローラーの UI/UX を参考にして設計・開発を進めていましたが、さまざまな課題に直面しました。

課題① スピード感を持ってデザインを固めていくことが難しい

RESZAIKO にはサイトコントローラーの開発時から社内に専任のデザイナーがいなかったため、社外のデザイナーと週一回のミーティングでデザインを進めています。 限られた時間で多くの画面のデザイン調整を行うことは難しく、簡単な画面はエンジニアがデザインすることもありました。しかし、デザイナー以外デザインルールの把握ができていない状況であったため都度認識を合わせる必要があり、スピード感を持って進めていくことができませんでした。

課題② プロダクト間で UI/UX の統一感を生み出しづらい

RESZAIKO は飲食店のスタッフが3つのプロダクトを横断して使用することを想定しています。横断して使用しても違和感のない操作を提供するために UI/UX を合わせる必要がありましたが、デザインや操作感に関する知見を開発チーム間でうまく共有できず、差異が生じてしまうことがありました。

これを防ぐために、社外のデザイナーに Figma 上でコンポーネントの置き場を作成してもらいました。 しかし、各プロダクトで使用するための仕組み化ができず、操作感の統一も Figma 上で十分に表現されていなかったため、うまく運用することができていませんでした。

課題③ デザインのクオリティの担保が難しい

同一プロダクト内で同じコンポーネントを使用していても、余白の取り方やコンポーネントの組み合わせ方など細かい部分まで統一することは難しいです。実際に、既存箇所を参考にしてできた画面は、大枠は同じでも完璧には揃えられておらず、画面ごとに少しずつ違いが出てしまいました。 また、デザインに関するチェック基準がないため、チーム内でのレビューもある程度までしか確認できず、デザイナーのレビューも毎回細部までチェックすることができない状態でした。

このような課題を感じながら当初は開発を進めていましたが、リリースが近づくにつれ、デザインのスピード感がボトルネックになり始めました。 そこで、エンジニアの中から比較的 UI/UX にこだわりをもつ3人が集まり、RESZAIKO デザインシステムを作成することになりました。

デザインシステム構築の流れ

このようにしてデザインシステムを作ろうという話になったものの、メンバーがエンジニアだけだったため、デザインシステムに関する知見が不足していました。 そこで、知見を得るために「ちいさくはじめるデザインシステム」という本を読むことにしました。

ちいさくはじめるデザインシステムbnn.co.jp

この本は、SmartHR 社のデザインシステムの取り組みを例にデザインシステムの構築・運用の方法について書かれています。 私たちはこの本を参考に以下の流れで進めていきました。

コンセプト設定

デザインシステムは、流行っているからや、なんとなくデザインの課題が解決しそうという理由で作成しがちです。 しかし、「ちいさくはじめるデザインシステム」には前提として目的が必要であると記載されていたため、まずデザインシステムを作成する目的を改めて定めるところから始めることにしました。

デザインシステムには正解がなく、「デザイン」という何らかの目的を機能させるための「システム」であり、システムとして成立させるために何らかの目的が必要

集まったエンジニア同士で現在感じている課題点を挙げ、それらの解決には何が必要なのか、どのような状態が理想なのかを話し合いました。 その結果、以下のようなデザインシステムのコンセプトとして明文化しました。


デザインシステム コンセプト

  • デザインと開発を効率化し、課題解決に集中できる環境を作り、リリースや改善サイクルを早くする
  • デザインに一貫性をもたせ、ユーザービリティとアクセシビリティを向上させる(サービス単体)
  • 3つのプロダクトを違和感のないユーザー体験を提供する
  • 非デザイナーとデザイナーとのコミュニケーションとして使用し、共通認識を作る手段とする
  • 非デザイナーが自走して簡易的なデザインを行えるようにする(デザインのよりどころにする)

構成決め

コンセプトを決めたところで、次にデザインシステムをどのような構成で実際に作成していくのかを検討しました。

構成を決めるにあたって、まずは他社のデザインシステムではどのような項目を採用しているのか調べました。 「ちいさくはじめるデザインシステム」にあるとおり、全てを網羅する必要はないため、調べたすべての項目を採用するのではなく、必要なものを取捨選択したり独自で項目を追加したりしました。

スタイルガイドには様々な種類がありますが、すべてを網羅している必要はありません。必要や目的・組織などに応じて柔軟に選ぶことができます。

私たちが特に参考にしたデザインシステムは、「SmartHR Design System」「Spindle」「デジタル庁 デザインシステム」の3つです。 「SmartHR Design System」はトークンやコンポーネントなど基本要素が網羅されているため、アウトライン作成の参考にしました。 「Spindle」は定義したコンポーネントの使用ルールがわかりやすくまとめられていたため、デザインルール作成の参考にしました。 また、今回作成するデザインシステムは元々コンポーネント置き場として使用していた Figma に定義したいと考えていたため、「デジタル庁 デザインシステム」のまとめ方を参考にして作成することにしました。

レビュー

デザインシステムのコンセプトと構成が決まったところで、他のプロダクトのデザインシステムを作成している方にレビューを依頼しようということになりました。 一休.com ではすでにデザインシステムが構築されているため、その作成に携わったデザイナーやエンジニアにレビューを依頼しました。

user-first.ikyu.co.jp

レビュー会では、定義するコンポーネントに対してどのように使うのかルールを記載した方が良いというアドバイスをいただきました。 これを受け、もともとルールは「デザインパターン」という名目でレイアウトに関することを定義する予定でしたが、これを「デザインルール」という名称に変更し、コンポーネントの使い方まで定義することにしました。 また当初は Figma 上でガイドラインの定義のみを行う予定でしたが、せっかくエンジニアが作成しているのだからライブラリまで作成したらどうかと提案をいただき、ライブラリの作成も試みることにしました。

そして、最終的に決定した構成がこちらです。


  • 利用の手引き: デザインシステム構築の目的・利用方法
  • デザインフィロソフィー: RESZAIKOプロダクトが大切にしていること
  • デザイントークン: デザインシステムにおける最小単位のスタイル定義
  • コンポーネント: UIを構成するための最小単位のパーツやアイコン
  • デザインルール: デザイントークンやコンポーネントを使用する際のルール
  • ライティングガイド: です/ます調や句読点の打ち方
    • チェックリスト: デザインシステムに則っているか判断するための確認項目

この中でも、まずは最小限でリリースしてみようということになり、主要部分となる「デザイントークン」「コンポーネント」「デザインルール」の策定を初回リリースの目標として進めていくことにしました。

作成

レビューのフィードバックを受けたところで、デザインシステムの作成に着手しました。 本業の実装も並行で行っていて、あまり時間を確保できない中、Figma に各自がトークンやコンポーネントを追加し、週に1回3人で集まってお互いが作成したものにフィードバックを行うという流れで進めました。 また、3人の中で合意が取れたものは、社外のデザイナーに確認してもらい、エンジニアとデザイナーの双方が問題なく使用できるように整えていきました。

実際にできたデザインシステムの一部をお見せします。

デザイントークン

コンポーネント

デザインルール

β版リリース!

初回リリースとして掲げていた「デザイントークン」「コンポーネント」「デザインルール」の作成がある程度完了したところで、β版のデザインシステムとしてチームに展開しました。

現在は、実際に社外のデザイナーや開発メンバーに利用してもらい、元々の定義で不十分だった内容を拡充したり、新たなUIについては都度定義を追加したりしています。 デザインシステムを通じて、デザイナーとのコミュニケーションが円滑になっただけでなく、エンジニア同士でもデザインに関する会話ができるようになり、コミュニケーションツールとしても機能しはじめています。

まとめ

本記事では、RESZAIKO デザインシステムの導入背景からβ版リリースまでの流れをご紹介してきました。

エンジニア主導でデザインシステムを構築してみると、前提知識が不足していたことから調査しなければならない事柄が多く、最初の段階ではリリースまでたどり着けるのか不安に感じることもありました。 しかし、実装で必要になるコンポーネントやデザインルールが明らかなので、Figma への定義のフェーズに移ってからは特に迷うことなく進めることができました。 自分たちが実装時に必要としているものをダイレクトに反映することができることは、エンジニア主導で作成するメリットだと思います。

今回デザインシステムを導入したことにより、当初感じていた3つの課題は解決できたのかという点についてですが、解決できた部分もあればもう少し手を加える必要がある部分もあると感じています。

課題① スピード感を持ってデザインを固めていくことが難しい

デザイナーとエンジニアの共通言語ができたことにより、デザインに対する質問の精度も上がり、コミュニケーションが取りやすくなったため、これまでよりスピード感を持って開発が進められるようになってきました。

今後は、さらにデザインルールなどをアップデートし、デザインについて考えやすい環境を整えていければと思います。

課題② プロダクト間で UI/UX の統一感を生み出しづらい

各プロダクト間でコンポーネントを検討しデザインに反映することがなくなったため、導入前よりも統一感を出すことができるようになりました。 しかし、実装レベルでの統一がまだ十分ではありません。これを解決するために、UI ライブラリとしてパッケージ化し、RESZAIKO の各サービスに反映していければ、さらに課題の解決につながると考えています。

課題③ デザインのクオリティの担保が難しい

ルールが定まったことで、誰が作成しても差異が出ないようにする基盤は整えられましたが、チェック時の効率はまだ改善の余地があります。 より効率的に確認できるようにするため、チェックリストの作成など、デザインシステムの拡張も進めていきたいと考えています。

運用を始めたばかりの現段階では、まだ全体的に改善の余地が多く残っています。 これからさらにデザインシステムをアップデートし、利便性を高めていきたいと考えています。

おわりに

全く知見がない中で始めたデザインシステムの作成でしたが、ありがたいことにデザインシステムをオープンに運用している企業が多く、参考にできるものが豊富にありました。そのおかげで自分たちなりにアレンジしてなんとか形にし、プロトタイプまで持っていくことができました。 知見がない中で、またエンジニア主導でデザインシステムを導入しようとしている方々にとって、この経験が一つの手がかりになれば嬉しいです。

RESZAIKO デザインシステムはこれからもっとアップデートさせていくので、今後もブログで発信していきます!

一休ではともに良いサービスをつくっていける仲間を募集していますので、興味を持っていただけたら、ぜひ一休の採用サイトをご覧ください。

Go Conference 2024にスポンサーしました & 一休はGoを活用しています

Go Conference 2024にスポンサーしました

CTO室プラットフォーム開発チームの山口(@igayamaguchi)です。

先日6/8(土)に一休でGo Conference 2024にスポンサーをさせていただき、スポンサーブースを出展しました。 gocon.jp

来ていただいた方はありがとうございます!

来ていただいた方と話していく中で、一休がGoを使っていることを知らない方がたくさんいることに気づきました。逆に、最近使い始めたばかりのRustの事例についてご存知の方のほうが多かったのです。これは、次のRustについての記事が多くの方に読まれたことによる影響だと思います。

user-first.ikyu.co.jp

実際には一休はGoを使っているサービスがたくさんあります。その点をアピールするため、この記事では一休のどのサービスでGoが活用されているかを紹介します。

一休がどのサービスでGoを使っているか

まず、一休ではいくつものサービスを提供しています。

会社紹介資料より抜粋

この中でGoが使われているサービスは以下の赤枠で囲われたサービスです。

ご覧の通り、Goが使われているサービスは多いです。
また、ユーザー向けのサービスとは別の社内プラットフォームでもGoが使われており、実際は上の図で表されている箇所以上にGoが活用されています。

ここからは、各サービスでのGo利用事例を個別に紹介していきます。

国内宿泊予約サービスでの活用

まず、一休の中で最も大きなサービスである国内宿泊予約においてGoは活用されています。
一休では国内宿泊予約サービスとして一休.comとYahoo!トラベル(LINEヤフー株式会社から運営を委託)を運営しています。

https://www.ikyu.com https://travel.yahoo.co.jp

宿泊施設を探すための検索を実行するバックエンドがGoで書かれています。バックエンドはgqlgenを用いたGraphQLサーバーになっており、ホテルやプランの検索、料金、在庫検索といったロジックが実装されています。他にも、全文検索エンジンであるSolrのインデクシングや、施設管理画面の一部APIなどもGoで書かれています。

ホテルの予約を行う処理、予約情報の閲覧ページはVB.NETですが、こちらも後々Goに置き換えていく予定です。

ふるさと納税、海外宿泊予約

国内宿泊予約サービス以外にもいくつかのサービスでGoは活用されています。
例えば宿泊予約時に割引クーポンを受け取れるふるさと納税サービスや、海外宿泊予約です。

https://furusato.ikyu.com/ https://www.ikyu.com/global/

これらのサービスは、社内では新しめということもあり、バックエンドは検索から予約まですべてGoで実装されています。

一休プラットフォーム

ユーザー向けサービス以外に、社内向けプラットフォームでもGoは使われています。一休ではいくつものサービスを運営しており、サービス間で共通のアカウントを利用し、貯めたポイントをサービス横断で使用したり、同じ決済の仕組みを使ったりできます。

そういった機能を各サービスで再実装することなく提供するために、一休プラットフォームとして複数のマイクロサービスを実装し、運用しています。具体的なサービスとして、現在は会員サービス、ポイントサービス、決済サービスがあり、これらはすべてGoで実装しています。

現在移行中の一休プラットフォームの図

一休プラットフォーム開発の実例については、2023年のイベントでの資料も参照してください。

speakerdeck.com

Goを選定してよかったこと

実際に国内宿泊予約や一休プラットフォームの開発に携わっているメンバーから、Goを選んでみてよかったことを聞いてみました。

  • 並行処理が言語組み込みで入っている。しかもそれが使いやすい
  • 言語仕様がシンプルで、入門から使えるようになるまでの時間が短い
  • 業務ロジックが大事なので、シンプルかつ堅く書けるのがよい
  • 一括処理や会計管理で大きめのデータを扱うときは非同期処理も書ける

総じて、Goは「シンプル、かつすばやく、それでいて堅牢に作れる」ことを重視する一休の技術選定方針に合致すると感じています。

おわりに

この記事では、一休がGo Conference 2024にスポンサーさせていただいたこと、一休では幅広くGoが使われていることを紹介しました。一休では、これからも生産的かつ高効率にサービスを開発/運用できるGoを活用して、サービスを成長させていきます!


一休では、ともに良いサービスをつくっていく仲間を募集中です。

hrmos.co

カジュアル面談も実施しているので、お気軽にご応募ください。

www.ikyu.co.jp

エンジニア向け社内イベントのご紹介と運営を経験してわかったこと

こんにちは。宿泊プラットフォーム開発チームの菊地です。

一休では月に一度、社内エンジニア向けにIkyu Tech Talkを開催しています。2022年から始まり、ありがたいことに2024年3月で丸2年を迎えることができました。
この記事では、Ikyu Tech Talkの2年間のふりかえりをしていきます。

また、私は社内イベントの主催が初挑戦だったので、どうやったらイベントを盛り上げられるのかと悩んだときもありました。
そこで、同じように自分の会社でTech Talkを開催してみたい人に向けてイベント運営の知見もお伝えしたいと思います。

開催のきっかけ

もともと定期的なプロジェクトの成果報告会はあるものの、業務で得たエンジニアリングの知見の共有をする場は設けられていませんでした。
あるとき「技術についてざっくばらんに話す場が定期的にあると楽しそう。一緒にやらない?」と声をかけてもらい、面白そうだったのでやってみることにしました。

Ikyu Tech Talkとは?

「技術のことならなんでもOK」と題して社内エンジニアに発表者をやってもらう60分の社内イベントです。 月に1回ペースでZoom開催しています。
カテゴリ別に過去の発表を抜粋してご紹介します。

自己学習の発表

個々人の技術研鑽の発表回です。業務では知ることができない興味関心分野を知ることができました。

  • GitHub Copilotで 次世代のコーディング体験
    • 正式リリース直後の2022年6月にGitHub Copilotについて発表してもらいました。これをきっかけにCopilotの業務利用を行うことになりました!
  • TypeScript による型レベルプログラミングに入門した話
    • 型定義の表現力の高さを活用して、tscにアルゴリズムを実行させるデモが鮮烈でした

プロジェクトのふりかえり

案件が終わったタイミングで、チームの皆さんに振り返りもかねて発表をしてもらいました。新しいフレームワーク・ツールを積極的に採用するスタンスなこともあり、初挑戦の技術のフィードバックが多かった印象です。チャット欄もおおいに盛り上がりました!

  • 宿特化型SNS YADOLINKでのアーキテクチャ選定
    • 一休で初めてReactを用いた事例でした。当時よくGraphQLクライアントとして選定されていたApollo Clientに対しての適不適の考察も興味深い内容でした。Apollo Clientについては以下の記事もご覧ください
  • 宿泊予約サイトの検索処理チューニング
    • 国内宿泊サイトの検索処理には複数のシステムが関わっています。それらを複合的にパフォーマンスチューニングしてレイテンシを半減させた実践的なテクニック紹介でした
  • レストラン予約サイトフロントエンドの今とこれから

専門性の高い部署の知見を広める

一休には、データサイエンス部・アーキテクトチーム・SEO対策チームといった専門性の高い部署があります。なかには「もっと早く知りたかった」「入社時の資料にしてほしい」という声をいただく発表もありました。

  • 猫でもわかる一休のデータ分析基盤(参加型)
    • 一休のデータサイエンス部は、各プロダクトのデータをもとに分析基盤を提供しています。分析基盤の全体像をキャッチアップできただけではなく、データ基盤を安定させるための実践的なテクニックが非常に面白い発表でした
  • 一休のサービスを支える インフラのはなし
    • プロダクトのネットワーク構成やデプロイフローについて、SREチームが解説しました。特に入社したての人にとっては垂涎の資料でした

Tech Talkの成果

Ikyu Tech Talkは完全任意参加のイベントとして運営してきましたが、開発組織メンバーの半数以上が参加し続けてくれています!
ここまで続けられてきたのは「エンジニアリングの話をするのが楽しいから」というのに尽きると思います。その一方、会社としてTech Talkを開催することで以下のような成果が得られました。

チームを超えてナレッジを共有できる

これまでは、成果報告会などのビジネス的な成果を知る場はあったものの、互いのナレッジを知る機会はなかなかありませんでした。Tech Talkはエンジニアリングの話を聞く場として貴重な機会になりました。

実際にSlackを探してみたところ、Tech Talkの発表を受けて他のチームのソリューションを取り込んでいるやりとりもありました!

発表時のZoomのチャット欄では、「ウチでは○○を使ってます」というように参加者からの知見も多く寄せられ、双方向での知見交流が生まれたのも成果だと思います。

発表の機会があることで、個々人の知識がよりブラッシュアップされる

プロジェクトに没頭している間は、知識が表面的なままになっていることがあります。Tech Talkを目標に、知識の精査や最新情報の確認をすることで、それらを自分の知見として昇華するきっかけにできます。

たとえば、あるプロダクトの新規リリースを行ったチームに発表をお願いしたところ、初期開発時の技術選定の是非を振り返った発表をしてくれました。
選定したソリューションの選定基準だけではなく、不採用にした他の案の理由や今振り返るとその選択は妥当だったのかの洞察も述べていて、今後の技術選定にとって価値のある資料になったと思います。

カジュアルに自己発信の経験を積む場を提供できる

自己発信の機会は貴重ですが、いざ外部の勉強会で発表しようとすると初心者には足が重いこともあります。 Tech Talkでは顔見知りが参加者なので、カジュアルに発表の経験を積むことができます。 採用活動をしている会社にとって社外で発表してくれるエンジニアは貴重ですが、Tech Talkを練習場として提供することができます。

社内イベントの運営をしてわかったこと

この記事を読んでいる方のなかには、以下のような悩みを持った人もいるかと思います。

  • 自分の会社でも社内イベントを開催してみたいけど、どうやったら盛り上がるだろうか、どう始めたらいいだろうか?
  • 社内イベントを開催してるけど人がなかなか集まらない、集まっても盛り上がらない
  • 登壇をお願いしても断られる、つらい

ここからは、社内イベントを開催したい方に向けて、Ikyu Tech Talkで得た運営のノウハウをお伝えします。

イベントがコンスタントに続けられる仕組みにする

Tech Talkの運営方針として、エネルギーが必要すぎて続けられなくなるよりもかけるエネルギー少なく長く運営できるイベントにすることを決めていました。
Zoom開催としたのも、イベント設営と集客に疲弊したくなかったからです。開催頻度も月1回くらいで「たまにやればいい」という気持ちで始めました。

発表を依頼したりイベント告知等の作業など、イベントの運営はただでさえ負担が大きいです。そのため、開催コストをできるだけ下げるのは非常に有用だったと感じました。
また一休ではリモートワークが導入されておりオフラインイベントにすると参加側の敷居も高くなってしまうため、双方にとってオンライン開催が最適でした。

発表者に対するリターンを設定する

発表準備や当日の精神的な負担が大きいので、モチベーションを高めるためにリターンを設けました。 具体的には「Tech Talk賞の開催」と「発表ごとに感想・メッセージの受付」を行っています。
  Tech Talk賞とは、半期に一度、最も面白い発表をしてくれた人を投票で決め表彰するイベントです。一休各サービスで使用できるポイントを贈っています。

また、毎度の発表後には、参加者に発表の感想・メッセージを書いてもらってそれをまとめてお渡ししています。発表中はどうしても参加者のリアクションがわからなかったり、面白い発表だったかなど不安を感じる人も多いです。実際に発表者の方からも、発表のフィードバックがもらえてよかった、という声をいただきました。

一方で、メッセージの回収率が20%程度にとどまっているのが今後の課題です。対策としてイベント中にメッセージの記入時間を設けたらどうかと検討中です。

Zoomのコメント機能を活用して積極的な参加を促す

多くの参加者にリアクションしてもらいイベントを盛り上げるため、Zoomのコメント機能を活用しました。
質問や感想をその場で話すには緊張してしまう人もいるため、テキストベースでコメント欄に書き込んでもらう形式にしました。書かれた質問は、発表の区切りの良いタイミングで司会が拾いその場で発表者に回答してもらいました。

また、司会以外の運営はちょっとした感想も意識的に書き込むようにし、コメント欄を盛り上げることを心がけました。今ではコメント欄がフランクな感想を言える場所として定着したため、とてもよい試みだったと思います。

まとめ

以上が社内イベント運営のノウハウです。 社内イベントでは、運営・発表者・参加者それぞれが継続できる仕組みを作ることが最も重要だと感じました!

さいごに

ここまで読んでくださりありがとうございます!
今回は社内イベント Ikyu Tech Talkの紹介と、社内イベントの運営をしてみて得た学びをまとめました。本記事が自社のエンジニア組織を盛り上げたい方の力になれたら幸いです。

また、いつもIkyu Tech Talkに参加&登壇してくださっている一休のエンジニアの皆さんへ。
この場を借りて感謝の気持ちを伝えさせてください。皆さんがポジティブに参加してくれるおかげで、Ikyu Tech Talkが楽しいイベントとして継続できています。いつも参加いただき本当にありがとうございます。

さいごになりますが、一休では社内イベントに積極的に参加してくれる、アウトプットが得意なエンジニアを募集しています。
興味がわいた方は、以下のリンクから面接応募及びカジュアル面談へのご参加をぜひぜひお願いいたします!!!

https://www.ikyu.co.jp/recruit/engineer/

https://hrmos.co/pages/ikyu/jobs/1745000651779629061