Location via proxy:   
[Report a bug]   [Manage cookies]                

Tech Leverages 月間技術活動レポート 8,9月号

8,9月中に、レバレジーズが関わった技術イベントのご紹介です。 自社イベントのみならず、共催イベントの開催、イベント登壇と多様な関わり方で、合計6件のイベントに参加しました!

主催・共催技術イベント

TSKaigiサブイベント #1 フロントエンド

8/6に、弊社の拠点である渋谷一丁目支店のセミナールームで、TSKaigi運営チームが開催する定期イベントの開催をしました。「フロントエンド」をテーマとし、TSKaigi2024の選考委員でもある”うひょさん”にトークを行っていただきました。

SREの組織と文化

9/6に、コミューン社、 弁護士ドットコム社の方を招いて、「SRE組織と文化」がテーマのLTイベントを開催しました。各社のSREが、実際に業務でどのようにSRE文化の浸透と醸成を行ってきたのか、赤裸々にお話ししていただきました。

Tech-Debt Meetup ~技術的負債と向き合うLT Night~

9/12に、渋谷スクランブルスクエアにある弊社の本社にて、「技術的負債との向き合い方」がテーマのLTイベントを開催しました。

OPTiM × レバテック ビジネス価値を追求する開発生産性

9/4に、OPTiM社とレバテックの共催でLTイベントを開催しました。OPTiMとレバテックでの 開発生産性の向上の具体的な取り組みについて発表しました。

イベント登壇

SRE MeetUp

レバテック開発部の金澤が、SRE MeetUpにて登壇しました。

speakerdeck.com

DevRel Guild Conference Mini

レバテックのDevRelメンバーの山本が、DevRel Guild Conference Miniに登壇しました。

speakerdeck.com

イベントスポンサー

SRE NEXT 2024 シルバースポンサー

8/3に行われたSRE NEXT 2024にて、レバテック株式会社がシルバースポンサーとして協賛しました。

We are hiring!

レバレジーズ株式会社では一緒にサービスを開発してくれる仲間を募集中です。 もしご興味を持っていただけたなら、こちらのページからご応募ください。

AIボット開発に挑戦!レバレジーズの開発サマーインターン2024レポート

自己紹介

レバレジーズのテクノロジー戦略室、AI/MLチームで二週間の就業型サマーインターンシップに参加した、早稲田大学創造理工学部経営システム工学科3年の住井と、慶應義塾大学理工学部情報工学科3年の小山です。

インターンシップの内容

僕たちは、NALYSYSというツールの問い合わせ機能を充実させるため、以下の二つのプロダクトを作成しました。

  • QAbot
  • QAbotの精度評価基盤.

作業を二人で分担することにし、QAbotのアプリ面の開発を住井、内部のRAGの精度向上・評価、QAbotの精度評価基盤の作成を小山が担当しました。メンターの方からいくつかのテーマを提示していただき、その中から我々の興味と能力に合わせて選択しました。

一日の流れは、以下の通りでした。

  • Good&New
  • チーム朝会
  • 作業
  • ランチ
  • 作業
  • 1on1

Good&Newはチームを跨いだアイスブレイクのようなもので、他チームの方と接する機会の一つでした。また、毎日1on1を実施していただいたので、相談もしやすく、サクラステージ内にある別オフィスの見学だったり、スクランブルスクエア内の本社での作業日を設けるといったような気軽な要望もスピード感を持って取り入れてくださいました。

技術スタック

今回は以下の技術スタックを使用しました。

QAbot

  • フロントエンド
    • React(Typesript)
  • バックエンド
    • Python
  • インフラ
    • AWS
  • UI
    • TailwindCSS
  • IaCツール
    • Terraform

評価基盤

  • フロントエンド
    • streamlit
  • バックエンド
    • Python
  • インフラ
    • AWS

QAbotのアーキテクチャ図は以下の通りです。

難しかったこと

触れたことない技術

NALYSYSの既存の技術スタックに合わせるため、今まで触れたことのない技術をいくつか使うことになりました。具体的には、React、Terraform、AWS Kendra、AWS Amplifyなどです。
特にTerraformは複雑で、最初は理解するのに苦労しました。しかし、最後の追い上げでなんとか形にすることができました。
これらの技術はReactやTerraformをはじめ、どれも現在多くのアーキテクチャで採用されているものです。今回のインターンシップはこれらの技術を学び始めるとても良いきっかけになりました。

RAGの精度と応答時間

今回は、精度も重視していたため、HyDE(Hypothetical Document Embeddings)、RAG-Fusion、Rerank、といった手法で精度改善を比較検討しました。しかし、実際にRerankやクエリ拡張、クエリ変換を処理に挟むと応答時間が増えることでUXの低下が著しく、精度向上とのトレードオフに悩まされました。シビアにUXを考える体験は、個人開発との違いを大きく感じました。

精度評価

実際にプロダクトに組み込むにあたり、一定の精度を担保する必要があったため、精度評価と精度改善に取り組みました。しかし、課題に着手した時点でNALYSYSには、評価に使用できるようなQA集が存在しませんでした。そのため、質を担保しつつ、評価用のQAを新たに作成する必要が生じました。

この課題に対し、単に現状の問題を解決するだけでなく、将来的な展開も見据えた解決策として、今後の機能拡張時や他サービスでのQAbot導入時にも活用できる、自動で評価用データセットの作成からRAGの評価まで行うツールを開発しました。

また、QAbotの評価の仕方自体も前例が少なく、難しい点でした。今回のRAGでは、プロダクトのヘルプページの内容を参照するようにしていたので、この時、特定のソースからQAを生成することで、自動生成のQAにGround Truthを与え、検索性能を評価しました。また、RAGの出力が「正確な回答」「一部不正確」「回答できていない」「間違った情報を含む」、のどれに相当するかを複数のLLM(GPT-4o, Claude)で評価し、スコアをAveragingすることで回答生成の評価を行いました。

社内・AI/MLチームの雰囲気

インターンシップの期間中は毎日出社しました。メンターの方とのコミュニケーションを密に取りながら作業を進めることができ、会社全体やAI/MLチームの実際の雰囲気を直接体験することができました。エンジニアは、ストレスフリーな環境で、チームの方も和やかで、非常に質問しやすいオーラを放っていました。

テクノロジー戦略室の室長の竹下さんは常にバランスボールに乗って作業しているくらいには自由でした。エンジニアのフロアであっても、和気藹々とした雰囲気があり、居心地が良かったです。

こういった環境のおかげでインターンシップでの学びを最大化することができたと感じています。

ランチ

ランチは、毎日別のチームの方に連れて行っていただき、渋谷のランチに詳しくなれた気がします。最終日ランチは宮下パークの筋肉食堂でした。フルリモートのインターンも多い中、出社してランチの機会があったことで会社の生の雰囲気が良く感じ取れた気がします。
AI/MLチームの社員の方は多種多様な企業から転職して来ており、前職のお話や、前職と今の違いだったりも聞く機会もありました。
一つのインターンシップで単なる技術的な学び以上の発見もあり、ランチタイムに感謝。

終わってみての感想

インターンシップ期間中に一定のまとまった成果物を完成させることができたのは、大きな自信につながりました。また、この10日間でいくつもの新たな技術に触れ、自分の技術スタックが増えるきっかけになりました。今回支えてくださった社員とメンターの方々、本当にありがとうございました!
レバレジーズのエンジニアがどういった働き方をしているのかだったり、実際の雰囲気を感じ取れるインターンシップでしたので、興味のある方はぜひ応募してみてください!!

recruit.leverages.jp

レバレジーズではAgile開発をやっていないのか?

はじめに

こんにちは、今年(2024年)の7月からレバレジーズにJoinした藤咲です。

私はこれまで「AgileでVUCAの時代をHappyに!」をモットーに、様々な開発チームにコーチングしてきました。 ですので、レバレジーズの「顧客の創造を通じて関係者全員の幸福を追求し、 各個人の成長を促す」という企業理念に非常に共感できました。 またグループ会社であるレバテックでは、昨年設立されたCTO室がAgile開発推進の役割も担うため、そこの所属となりました。

まだJoinしてから2ヶ月半というタイミングではありますが、レバレジーズでのAgile浸透へのFirst Stepについてご紹介します。

Agile CoP、はじめました。

レバレジーズではAgile開発に取り組んでいるものの、なかなか浸透しない上に効果がイマイチわからないという声が上がっていました。実際に各開発チームの進め方を見ていると、自信をもってスクラムをやっているチームと、なんとなく用語を使っているだけのチームが混在していました。

そこで、まずはAgile CoPというコミュニティを作ることで、組織内での知見を共有することから始めることにしました。

弊社におけるAgile CoP(CoP: Community of Practice)の位置付け

Agile CoPを作ろう!と声をかけたら40人も集まったが、、、

まずは私自身が発起人となり、レバテックを含むレバレジーズグループの開発者全体に向けてAgile CoPを作ろうとをSlackで投げかけると、全体の約20%にあたる40名もの方が参加意思を示してくれました。 そしてKickOffを実施したところ、多くの方がAgile開発の実践経験者であることがわかりました。

ところが、皆さんの自己紹介を聞いていると、

「なんちゃってAgile開発」

「Agileっぽい開発」

「Agile開発と呼んでいた何か」

という表現が非常に多かったんです。

つまり、Agile開発を実践してはいるけれども、今自分たちがやっている開発を自信を持ってAgile開発だと言えない状況であるということがわかりました。

例えば、

  • スクラムで開発している(?)けれどもスクラムマスターはいない
  • スプリント単位にインクリメントの価値を高められていない
  • 事業部を巻き込めておらず開発チームだけで回している

といったように。(まぁ、Agileあるあると言えばそうですが。)

Agile CoPをAgileに運営する

現状は把握できたので、どうすればAgile CoPの活動を通して「自信を持ってAgile開発を実践している」と言える状態にできるか、を次に考える必要があります。 これは今や常套手段でもありますが、弊社ではコミュニティ活動自体をAgileに進める、という方法をとっています。

具体的には、最低限以下のルールで運営を開始しました。

  • 週に1回30分のセッションを開催(1週間のイテレーション)
  • テーマは悩みや相談ごとをメンバーが持ち寄り(バックログ)
  • 各回の終わりに次回のテーマを1つのみ決める(WIP制限:1)
  • 進め方自体の改善提案も常にWelcome(ふりかえり)
  • みんなが主役!(マインドセット)
  • 管理はAsanaボードで!(チケットドリブン)
    Agile CoPタスクボード(Asana)

なんちゃってAgile開発からの脱却を目指す今後の取り組み

まだまだ立ち上がったばかりでご覧の通りバックログも積み上がっていない状態ですが、千里の道も一歩から、ということでスモールにスタートを切っています。 各チームの悩みやうまくいかいない状況に対して、コミュニティでの活動を通して解決のヒントや糸口を掴み、自ら改善していく。そんなメンバーが集まるコミュニティを目指し今後も活動していきます。

一方で、コミュニティ内だけでは解決しきれない課題というのが既にいくつか散見されています。

具体的には、

  • スクラムマスターを目指せるキャリアパスやポジションがない
  • 事業部を巻き込んだ形での推進体制が作れていない

といった、組織の制度や体制に関わる問題です。

そこはCTO室として動かなければならない領域でもあるので、コミュニティと経営をつなぐ立場として、中長期的な対応にもチャレンジしていきます。

レバレジーズの開発メンバーのみんなは、より良い実践をしていきたいというマインドは既に十分に持っています!

そういった前向きなメンバーと一緒にチャレンジしたいという方、ぜひ私たちとHappyに働いてみませんか? recruit.leverages.jp

テックフェス2024夏 レポート

はじめに

こんにちは。今年の4月にレバレジーズ株式会社に入社しました古川修慈です。

本記事では 8/8(木) に開催されたテックフェスという社内イベントの様子をご紹介します。
BuySell Technologie社CTOの今村氏による基調講演や、レバレジーズグループが持つ技術的な課題とその解決方法を紹介するセッション、事業部の垣根を越えて楽しくゲームをする様子を紹介するので、ぜひ最後までご覧ください。

テックフェスとは

レバレジーズグループに所属するエンジニアを対象に、社内で半年に一度行われているイベントです。一日を通して、技術的な課題解決事例やノウハウを共有したり、トレンドの技術を解説することで、社内の全てのエンジニアの技術力を伸ばすことを目指します。
今年の夏は、「次代をつくる」という意味を込めて、「Let’s Hack Leverages 〜そして伝説へ〜」というテーマで開催しました。

基調講演

今回はBuySell Technologie社CTOの今村氏に「CTO視点で語る、これからの時代に活躍するエンジニア像について」というテーマでお話していただきました。

登壇者紹介

今村雅幸 氏

  • 株式会社BuySell Technologies 取締役CTO
  • 一般社団法人 日本CTO協会 理事
  • ファインディ株式会社 社外取締役
  • 株式会社イベンターノート代表取締役
  • 投資先 技術顧問

ヤフーに新卒エンジニアとして入社後、新規事業や特許取得に追従。独立しVASILYを起業後、取締役CTOとして200万人以上が利用するファッションアプリの開発をリードする。M&AでZOZOへ売却後は、ZOZO(旧ZOZOテクノロジーズ)に執行役員VPoEを経てCTOへ就任。ZOZOTOWNリプレイスや400人を超えるエンジニアの採用・教育、情報システム、セキュリティなど幅広くDXを推進する。その後、BuySell Technologiesの取締役CTO就任。全社のテクノロジー戦略や研究開発、エンジニアリング組織マネジメントなどテックカンパニー化を推進する。

コンテンツ

「素晴らしいエンジニア」の定義から始まり、それがどのような要素から構成されるかを公演していただきました。参加されていたみなさんは今村氏のお話に一気に引き込まれているようでした。
その後に、具体的にどう素晴らしいエンジニアになるかを語っていただきました。圧倒的なインプットというすぐ業務に活かせるものから、技術トレンドを抑えるというキャッチアップ的なものまで、さまざまなTipsを紹介してくださいました。
マクロな視点で個人的に印象に残った言葉が「結局事業貢献を作るためには、自分達が良いと思う文化を作っていく必要がある」です。もしそれができれば、事業貢献が生まれ、新たに良い文化が生まれるというサイクルが生まれる、という点も教えていただきました。


セッション

発表者のみなさん、ありがとうございました。

JestランタイムをHackしてCIの実行速度を3倍にした話 (レバレジーズ NALYSYSグループ 桐生 直輝さん)

「APIが遅い」という問題に対処するために、

  • Jestのソースコードを読み、原因を突き止める
  • Jestの制約を掻い潜って高速化する

の順序で発表をしてもらいました。
単純な事例だけでなく、Jestのソースコードを読むコツや、一見意味がわからないエラーの原因を突き止めるための方法も紹介していただきました。

生産性改善を徹底的に考え、実践してみた (レバレジーズ アジャイルエフェクトチーム 西 慎一郎さん)

自分のチームで実際に取り組んだ生産性改善の具体的なTipsとツールを紹介してもらいました。
具体的には、Miro、 Cursor、Gamma などを用いたメソッドを共有してくれました。
「0から作ることを極力やめる」という信念のもと、AIといった最新の技術から、USMやモププロなど一般的なプラクティスまで広く取り入れていた点が印象的でした。

LT

発表者のみなさんありがとうございました。
今回はNALSYSチームから多くの方が発表がありました。
5分という短い時間でしたが、課題から解決策までわかりやすくまとめた発表が多かったです。

以下全てのタイトルと発表者です。

  • 大量ユーザーへのSlack通知を実現せよ (レバレジーズ NALYSYSグループ 岡本 侑樹さん)
  • 競艇自動予想アプリつくってみた (レバレジーズ CXグループ 田上 達也さん)
  • AgileでVUCAの時代をHappyに! (レバレジーズ CTO室 藤咲 浩さん)
  • FEテストの技術選定 (レバレジーズ NALYSYSグループ 松本 悠太郎さん)
  • GCP小話 (レバレジーズ NALYSYSグループ 香川 淳さん)
  • ムダヅモなきテスト戦略 (レバレジーズ NALYSYSグループ 下畑 剣一郎さん)

テックバトル

参加されたみなさんありがとうございました。
テックバトルでは運営チームが作った技術用語の百人一首を行いました。経験度合いに左右されず楽しめる内容だったため、大いに盛り上がりました。


懇親会

写真を取ろうと思っていたのですが、盛り上がりすぎてうっかり忘れてしまいました。
技術のことからプライベートのことまで、事業を横断して幅広い交流が生まれていました。

最後に

今回の記事では、テックフェスのレポートを書かせていただきました。LTという短時間の発表とは思えないほど内容が濃く、セッションではまさに事業部のナレッジが凝縮されていました。基調講演では、エンジニアとしての生き方を考えることができました。

レバレジーズは、社内で技術ノウハウの共有を行なうイベントはもちろん、外部から著名な方をお呼びして貴重な話を聞く機会を積極的に設けています。 レバレジーズに少しでも興味を持っていただけた方は、こちらからエントリーをお願いします。

recruit.leverages.jp

Tech Leverages 月間技術活動レポート 7月号

7月中に、レバレジーズが関わった技術イベントのご紹介です。 今月は、イベントへのスポンサーと登壇をメインに7件ありました。

イベントブース出展

Developer eXperience Day 2024

CTO協会が主催しているイベントで、レバテックがゴールドスポンサーとして協賛しました。ブースも出店し、七夕が近かったので「レバテックに願いを」という、エンジニアの願いを短冊に書いてもらう企画も行いました。数多くの登壇者、参加者の方に書いて貰い、大盛況でした。お書きくださった皆様、ありがとうございます。

Platform Engineering Kaigi 2024

こちらもゴールドスポンサーとして協賛し、ブースの出展をしてきました。こちらも、「レバテックに願い」を実施し大盛況でした。

イベント登壇

Developer eXperience Day 2024: 経営層を開発者体験向上にコミットさせる方法論 ~ Developer eXperience Day 2024 ~

TiDB User Day 2024: TiDBは銀の弾丸になるのか? ~ レバテックの課題と新たな挑戦 ~ TiDB User Day 2024

Platform Engineering Kaigi 2024: いつPlatform Engineeringを始めるべきか?〜レバテックのケーススタディ〜 Platform Engineering Kaigi 2024

Developers Summit 2024 Summer: 開発と事業を繋ぐ!SREのオブザーバビリティ戦略 ~ Developers Summit 2024 Summer ~

D-Plus Tokyo #4: ~しくじり事例から学ぶ!開発生産性の取り組みLT会~ FourKeysだけで開発生産性 は測れないと気付くまでの話

おまけ

【レバテック開発部に聞いた】ITエンジニアにおすすめの本18選!という記事も公開しています。良ければこちらの記事もお読みください。

We are hiring!

レバレジーズ株式会社では一緒にサービスを開発してくれる仲間を募集中です。 もしご興味を持っていただけたなら、こちらのページ からご応募ください。

Elasticsearchによるマイクロサービス間検索の基盤をNetflixの事例を参考に構築した話

はじめに

レバレジーズシステム本部 NALYSYSグループ テックリードの桐生です。

NALYSYSとは、ピープルマネジメントを支援する「NALYSYSモチベーション管理」や労務業務を効率化する「NALYSYS労務管理」などの機能を多数持った、人事労務に関わる課題を解決するためのSaaSです。

そんなNALYSYSでは、今年4月に新たに「NALYSYS従業員ライブラリ」をリリースいたしました。こちらのプロダクトではマイクロサービスを跨いだ検索を実現する必要があったのですが、これにより今までにない設計上やパフォーマンス面の問題に直面し、また短い納期の中でこの問題を解決する必要がありました。今回の記事では、これらの問題をNetflixの事例を参考に爆速で解決に導いた取り組みをご紹介いたします。

NALYSYS 従業員ライブラリについて

現在のNALYSYSは、「NALYSYS Admin」に登録された従業員の基本情報を中心として、それにぶら下がる形で「NALYSYSモチベーション管理」や「NALYSYS労務管理」などに追加の情報を保持しています。同じ従業員の情報であっても分野ごとに異なるプロダクトに保存されているため、これらのデータを活用するには複数のプロダクトを行き来する必要があり、ユーザーにとって不便な状態となっていました。

これを解決するために企画されたサービスがNALYSYS従業員ライブラリです。

従業員ライブラリが新たにNALYSYSに加わることで、複数のプロダクトに分散している情報を集約して閲覧することができ、プロダクトをまたいだ従業員の検索も行うことができるようになります。

全プロダクトのデータを集約するという性質上、権限やパフォーマンスに関して今までにない課題に直面することとなりました。また、今回は企画立案〜リリースまでが3ヶ月という短いスケジュールだったため、その期間で実現可能な方法を選ぶ必要がありました。 本記事では、直面したさまざまな課題の中から「プロダクト横断検索」に関わる部分をピックアップしてお届けします。

マイクロサービス間検索における課題

NALYSYSのバックエンドではマイクロサービスアーキテクチャを採用しており、それぞれのマイクロサービスごとに独立したデータベースを持っています。(マイクロサービスアーキテクチャでは各サービスの独立デプロイ可能性を確保するためにデータベースを分離する必要があります)このため、マイクロサービスを跨いだ検索を行おうとすると、検索に利用したいデータが複数のデータベースに分散しているという点が問題となります。具体的には、愚直に検索を実装する場合、複数のマイクロサービスに対してそれぞれデータ取得操作を行なった後、それらを集約して検索結果を構築する必要があります。特に、特定のマイクロサービスに関する検索条件がゆるい場合には大量のデータをロード・転送しなければならないため、データ量に対してスケールしにくくなってしまいます。実際に既存のプロダクトでも在籍状況+プロダクト固有の情報で検索する場合などに同様の問題に直面し、パフォーマンスが低下していました。

今回は、この問題を根本的に解決するため、単一の検索用データベースに全てのサービスのデータを集約することとしました。具体的には、以下のNetflixの事例を参考に、マイクロサービス間に分散したデータをElasticsearchに集約してインデックス化し、横断的な検索を実現します。

netflixtechblog.com

検索システムの構成

構築した検索システムの概要を以下に示します。

先ほど紹介したNetflixの事例と同様、Elasticsearchの検索インデックスに各サービスからかき集めた従業員の情報を合成して登録していきます。実際にユーザーが検索リクエストを送った際には、従業員ライブラリのマイクロサービスがそれをElasticsearch用の検索クエリに変換して検索を実行します。検索処理は全てElasticsearch内で完結し、DBのスキャンが必要ないため高速な検索処理を実現することができました。

インデックスの更新方法について

Elasticsearchに登録されている従業員データは元々のサービスからコピーされたものであるため、元のデータが更新された場合これを随時インデックスに反映していく必要があります。

先ほどのNetflixの事例では、各マイクロサービスが送出するデータ更新イベントをトリガーにしてElasticsearchへのデータ再登録を行うという手法をとっていました。Netflixのシステムでは元々Kafkaに変更イベントを送出する仕組みが整っていたため、このような手法を少ない労力で実装できたようです。

一方、NALYSYSにはNetflixで行われているような変更イベントを流す仕組みがありませんでした。マイクロサービス間を疎結合にするという観点で、Netflixと同様にメッセージベースのやり取りを実装するのが望ましくはあったのですが、開発期間が短い中でそのような仕組みを設計・構築する余裕がなかったため、今回は代わりにLogstashのJDBC Input Pluginを活用した変更検知を実装しています。

JDBC Input Pluginを用いると、データベースに対して定期的にクエリを発行し、データの差分を取り込むことができます。以下の公式ブログに詳しい実装方法が説明されています。

www.elastic.co

この方法を用いる場合、Logstashのデプロイおよび必要な設定ファイルの作成を行うだけでインデックスの自動更新を実装することができるため、自前で更新のための仕組み(差分イベント送出・検知)を実装するのに比べて大きく工数を削減することができます。一方で、各サービスのデータベースの構造とLogstashの設定ファイルが密結合になるためメンテナンス性が低下するという問題も抱えています。今回は短納期を実現するために必要な負債としてこれを受け入れることとしました。

まとめ

ここまで述べた取り組みによって、高速な横断検索機能を予定期間内に作り上げることができました。今回は従業員ライブラリに特化した仕組みとなってしまったので、今後は他のプロダクトにもこの仕組みを展開しつつ、メッセージベースの変更検知によってサービス間の結合度を下げる取り組みも行っていきたいと考えています。

レバレジーズでは、ソフトウェアの力で人事労務に関わる課題解決に挑戦する仲間を募集しています!ご興味のある方はぜひ採用サイトをご覧ください!

Tech Leverages 月間技術活動レポート 6月号

6月中に、レバレジーズが関わった技術イベントのご紹介です。
自社開催から、共催、スポンサー、運営の手伝いと多様な関わり方で、合計5件のイベントに参加しています!

主催・共催技術イベント

イベントグループ「Tech Leverages」始動

イベント開催プラットフォームのconnpassにて、Tech Leverages グループをリニューアルしました。今後弊社で開催するイベントはこちらで公開していきますので、興味がある方はグループ登録をお願いします。

渋谷一丁目支店・初技術イベント: Agile Effect MeetUp なんちゃってスクラム開発からの脱却

6/27に、弊社の新しい拠点である渋谷一丁目支店のセミナールームで、Agile Effect MeetUpを開催しました。スクラムマスターの服部 翔太氏や、株式会社aby CTO 向後 澄哉氏にご参加いただき、パネルディスカッションを行いました。

イベントブース出展

AWS Summit 2024 ブース出展 & ミニセッション登壇

6/20,6/21に幕張メッセで開催されたAWS Summit 2024で、レバテックプラットフォームでのAmazon QuickSightの活用事例を紹介するブースを出展しました。

また、ミニステージにて、弊社エンジニアの塚原と内藤が、技術の詳細の発表も行って来ました。

イベント登壇

UX Design Conference 2024:『VoLT:レバテックのデザインシステム』電光石火の構築プロセスと目指す未来

弊社CTO室テックリードの河村とプロダクトとデザイン責任者の山本が、UX Design Conference 2024で登壇しました。

イベントスポンサー・手伝い

日本CTO協会 新卒合同研修 会場スポンサー

6/19に日本CTO協会様が実施されている合同新卒研修で、会場スポンサーとしてレバレジーズ本社のセミナールームを提供いたしました。今回の内容は「インテリアデザインを通したアジャイル開発の体験」で、グループワークを通してアジャイル開発がどのように進むかを疑似体験するというものでした。

ScalaMatsuri2024 運営スタッフとして手伝い

6/8,6/9に、国際交流館 プラザ平成で開催されたScalaMatsuri2024に、弊社テクノロジー戦略室室長 竹下が運営スタッフとして開催を手伝ってきました。コロナ後初のフルリアル開催となり、日本中のScala使いが集結しました。

また、竹下が、酒を飲みながらLeetCodeを解くという「アルコーダー」の発表?を行ってきました。

We are hiring!

レバレジーズ株式会社では一緒にサービスを開発してくれる仲間を募集中です。 もしご興味を持っていただけたなら、こちらのページからご応募ください。

レバレジーズ テックフェス2024冬レポート

アイキャッチ

はじめに

こんにちは、レバレジーズ株式会社の檜垣・南です。本記事ではレバレジーズグループ全体のエンジニアが参加するテックフェスの様子をご紹介します。基調講演や、社員によるトークセッションなどについて書いていますので、ぜひ最後までご覧ください。

テックフェスとは

レバレジーズグループに所属するエンジニアを対象に、社内で半年に一度行われている技術の祭典です。エンジニアが新しい技術に興味を持ち、勉強をするきっかけを作ることを目的とし、グループ全体の技術力向上を目指します。2月14日に「速さと質の次へ~史上最速でコアコンピタンスを高める組織~」というテーマでテックフェス2024冬を開催しました。

AWS

AWSソリューションアーキテクチャの苅野 秀和氏に「AWS を使って価値提供 に集中しよう」というテーマで特別セッションをしていただきました。AWSのサービスに限定せず、AISASフレームワークを使った戦略の考え方などを発表していただきました。また、求人検索のパーソナライズやBedrockを利用した営業活動支援の最適化など、人材業界でのユースケースも紹介していただきました。人材業界にサービスを多く展開するレバレジーズのエンジニアにとって、コアコンピタンスを見つけるきっかけになったのではないかと思います。

アジェンダ

  • AWSを用いたデータ活用
    • High value & low riskの探索
    • Personalize
    • Bedrock
    • 人材業界でのユースケース
  • 開発者とAWS
    • セキュリティ
    • CodeCatalyst

AWSセッション

基調講演

徳丸浩氏に「今どきのウェブアプリでは脆弱性はどのように発現するのか?」という題名で、現在のアプリケーションにおいて脆弱性がどのように発現するのか、Teratail他のネットの記事のコードを参照しつつ解説していただきました。

登壇者紹介

徳丸浩 氏

  • EGセキュアソリューションズ株式会社 取締役CTO
  • イー・ガーディアン株式会社 CISO
  • 独立行政法人情報処理推進機構(IPA)非常勤研究員 技術士(情報工学部門)
  • 著書: 「 体系的に学ぶ 安全なWebアプリケーションの作り方脆弱性が生まれる原理と対策の実践(ソフトバンククリエイティブ) 」

1985年京セラ株式会社に入社後、ソフトウェアの開発、企画に従事。1999年に携帯電話向け認証課金基盤の方式設計を担当したことをきっかけにWebアプリケーションのセキュリティに興味を持つ。2004年同分野を事業化。 2008年独立して、Webアプリケーションセキュリティを専門分野とするHASHコンサルティング株式会社(現EGセキュアソリューションズ株式会社)を設立。 脆弱性診断やコンサルティング業務のかたわら、ブログや勉強会などを通じてセキュリティの啓蒙活動をおこなっている。 2023年イー・ガーディアングループのCISOに就任。セキュリティレベル向上だけでなく、活動を通して得たノウハウをサービスやセミナーコンテンツにも還元し、広くセキュリティの啓蒙活動に邁進。

アジェンダ

  • アプリケーションフレームワークと脆弱性対策
  • フレームワークとSQLインジェクション
    • Teratailの質問から
    • LaravelでSQLインジェクション脆弱にする
  • フレームワークとクロスサイトスクリプティング(XSS)
    • LaravelでXSSが発生するケース
    • ReactのようなSPAフレームワークの場合
  • SPAとCORS(Cross-Origin Resource Sharing)
  • フレームワークと認可制御

基調講演

セッション

発表してくださった皆さんありがとうございました。

最優秀の発表について

大規模なORMバージョンアップ作業を乗り越えた話 (レバレジーズ NALYSYSグループ 桐生 直輝さん)

speakerdeck.com

概要

大きめの破壊的アップデータがあったTypeORM 0.2 -> 0.3 移行について

  • ts-morph を用いたコードの自動置き換え
  • 移行用ライブラリによる漸進的な移行
  • 自動テストを活用した影響調査

の順序でお話し頂きました。

自作の移行用ライブラリを作成し、徐々に0.2 から 0.3に変更を進めて、 1人月+レビュー工数でアップデート作業を終えられていました。

LT

発表一覧

発表してくださった皆さんありがとうございました。

最優秀の発表について

桃栗3年、レコメンドエンジン5年 (レバレジーズ データ戦略室 阪上 晃幸さん)

speakerdeck.com

概要

レコメンドアルゴリズムのリプレイスについて

  • 黎明期
    • データ戦略室の発足時から将来を見据えて着工
    • 事業部長への提案〜アルゴリズム開発
  • 挫折期
    • Covid-19がレコメンド
    • プロジェクトを襲う
  • やり直し期
    • 全く新しい観点でアルゴリズムを開発
  • 新体制
    • アルゴリズムに足りていなかった現場の意見を反映し、使えるものに
  • 熟成期
    • 可用性を高め、LTSF実装に繋げていく1年
  • 離陸期
    • LTSFの内部でレコメンとAPIを使ってもらう

の順序でお話し頂きました。

懇親会

テックフェス終了後は、懇親会も開催。ピザやお寿司、おにぎりを食べながら発表者へ話を聞きに行ったり、他チームの方と交流を深めている様子が見られました。

運営メンバー打ち上げ

後日、運営メンバーで打ち上げに行きました。写真を撮ろうと思っていたのですが、話が盛り上がりすぎてすっかり忘れてしまいました。

最後に

今回の記事では、テックフェスのレポートを書かせていただきました。徳丸浩さんの貴重なお話を聞けたり、社内のエンジニアから普段は聞けない話を聞けて非常に面白かったです。

社内で技術ノウハウの共有を行なうイベントがあったり、外部から著名な方をお呼びして貴重な話が聞ける環境のレバレジーズで皆さんも一緒に働いてみませんか? レバレジーズに少しでも興味を持っていただけた方は、以下のリンクからエントリーをお願いします!

recruit.leverages.jp

【Frontend Night: App Router本番運用企業が語る!Next.js新機能活用法】で発表しました

レバレジーズ株式会社 レバテック開発部の堀内です。

2024/05/29に、PharmaX社、ANDPAD社、弊社の3社による共催イベント「Frontend Night: App Router本番運用企業が語る!Next.js新機能活用法」が開催されました。
Next.jsのApp Routerを実際に本番運用している会社が集まり、App Routerを利用した開発において良かったことや工夫したことを発表しました。

私は『App Routerの開発で気をつけたいこと3選』というテーマで発表しましたので、そのスライドを共有します。
App Routerを利用したプロジェクトを通して、ハマったところや失敗したところがいくつかあったため、気をつけたほうがいいこととして3つ紹介させていただきました。

speakerdeck.com

We are hiring

現在レバレジーズでは一緒に働いてくれる仲間を募集しています。
ご興味のある方は、以下のリンクからご応募ください。

recruit.leverages.jp

TerraformによるIaCの標準化を通じた、全社規模の開発体験の向上への取り組み

はじめに

 レバレジーズ株式会社 テクノロジー戦略室 SREチームの中野です。レバレジーズでは「SRE化を通して、Developer Experienceの改善、事業の拡大への対応、お客様に信頼されるサービスの提供を実現する」をミッションとして、Embedded SREメンバーと協力しながら、サービス改善の文化的土俵の構築や開発生産性の向上を進めています。
 この記事では、開発体験を向上させるための取り組みとして、社内標準となるIaCツールの選定、IaC化の負荷軽減への取り組みについてご紹介します。具体的には、社内標準ツールの選定では決定に至るまでのプロセスや方法をご紹介し、IaC化の作業負荷の軽減への取り組みでは、全体最適を狙った下記のライブラリ・テンプレートの作成についてご紹介します。

  • Terraform Modules
  • GitHub Composite Actions
  • GitHub Repository Template

 また、この記事を通して、弊社の開発体験の向上における取り組みを知って頂くと共に、全社最適を狙ったIaC化の推進について是非ともご参考頂ければ幸いです。それでは、以下で背景を挟みつつ具体的な取り組みについてご紹介します。

背景

 サービス開発体制のSRE化を進めやすくするために、インフラ構築・管理の省力化でIaC化を進めています。しかし、実際にはAWS CDK、AWS CloudFormation、Terraform等の複数のツールが利用されており、開発チーム・SREチームの双方において作業負荷がかかってしまっています。
 実際、ツールの乱立により、開発チームではIaCツールの理解度・習熟度がバラついており、開発チーム間でのナレッジ・ノウハウの共有が困難だったりします。SREチームでも、開発チーム毎に異なるサポートが必要となり、サポート負荷が高くなりがちです。
 この様な状況を解消するためには、ツールの乱立を最小限に抑え、IaC化を低負荷・低工数で進められる様にする必要があると考え、社内標準となるIaCツールの選定と、IaCツールやCI/CDにおけるライブラリ・テンプレートの作成を進めることになりました。

社内標準となるIaCツールの選定

ツール比較

 まずは、社内標準となるIaCツールの比較から始めました。ツールの認知度・利用度の高さを考えてTerraform・AWS CDK・Pulumi・CDKTF・OpenTofuから比較し、Terraform・OpenTofuが最良の選択肢として残りました。理由は下表の通りです。

比較観点 評価理由
成熟度・カバー範囲 殆どのパブリッククラウドに対応しており、SaaSでも対応範囲が広い。
ツールの学習負荷 HCLはJSONライクで学習しやすく、リソース設定が宣言的で見通しが良い。
構築・変更の負荷 リソース設定が宣言的なため、クラウドサービスの構築・更新でコード変更とズレの無い状態差分で期待通りに適用出来る。
状態変更の容易性 import・moved・removed等のブロック設定により、ツールで管理される状態の追加・変更・削除をコードベースで容易に実施出来る。
GenAIとの相性 リソース設定が宣言的なため、簡単なプロンプトで一定以上のクオリティでサンプルコードを生成出来る。

リスク調査

 ツール比較でTerraform・OpenTofuが最良の選択肢として残りましたが、今後IaC化を問題無く推進していくためにツールの将来的なリスクも考えておく必要があり、ライセンス変更によるTerraformの利用制限の可能性について調査しました。
 ライセンスに関する公式情報によれば、Terraformの利用範囲は従来通りでリスクはありませんでした。実際、HashiCorpの競合製品においてはHashiCorp製品が埋め込まれていれば利用制限が発生しますが、社内/個人によるHashiCorp製品の利用においては制限は無いとのことでした。 
 一方で、OpenTofuは今後のツールとしての安定性・充実性が現時点では見込めなさそうなため、Terraformの方がより安定的でリスクが低いツールであると判断しました。

www.hashicorp.com www.hashicorp.com www.hashicorp.com

選定結果・例外

 以上の比較・調査の結果を踏まえ、Terraform を社内標準ツールとして採用しました。今後はTerraformでIaC化を推進していく予定です。しかし、Terraformの導入・移行における費用対効果が必ずしも高く無いパターンもあり、下表を例外として規定しました。これらを考慮しながらIaC化を進めていきます。

例外パターン 対応方針
Terraformへのツール移行 他ツールで管理されているパブリッククラウドやSaaSでは、移行コストと改善効果性のバランスを考え、Terraformへの移行を検討する。
Terraformによるサポートが弱い部分へのIaC化 Terraformのサポートが未対応、またはサポート範囲が狭い部分では他ツールの利用を認める。
外部サービスの仕組みにおけるTerraformの導入 パブリッククラウドやSaaSで提供される仕組みにおいて、Terraform以外の手段で構築されている場合は、その手段の使用を認める。
一時的な利用のシステムへのTerraformの導入 プロトタイプや実験的な環境等の、一時的な利用が確実に見込まれる様なシステムでは、TerraformによるIaC化は強制しない。

ライブラリ・テンプレートの作成

 次に、IaC化を低負荷・低工数で推進するために、IaCの移植性・再利用性等を高める様なプラクティスの検討を進めました。Terraformを利用している開発チームにヒアリングしたところ、下記の課題感が出てきました。

  • 実装の際にクラウドサービスの仕様把握が必要で、実装における作業負荷が高い
  • 宣言的な設定のため、リソースが多くなると設定管理における認知負荷が高まる
  • Git RepositoryやCI/CDにおける社内標準の構成が無く、設計・初期作業で時間がかかる

 これらを解決するためには、Terraformにおける社内標準のライブラリ・テンプレートを作成する必要があると考え、Terraform Modules・GitHub Composite Actions・GitHub Repository Templateを全社向けに開発することになりました。

管理方針

 SREチームがライブラリ・テンプレートをメンテナンスしていく予定のため、テクノロジー戦略室向けのGitHub Organizationの配下でライブラリ・テンプレートを管理することにしました。また、ローカルやCI/CDでライブラリを利用する際に、PATをベースとしたアクセス認証でライブラリをダウンロードする様にしました。

作成方針

Terraform Modules

 全社最適のパターンとして、個々に依存しない手段を用いて全社最適を図るか、または個別最適の手段を組み合わせて全社最適を図るかの2種類が考えられ、そこからTerraform Modulesにおける次の構成方針を洗い出しました。

  • (1) 社内のサービス・システムに合わせたTerraform Modules
  • (2) クラウドサービスのリソースに対応するTerraform Modules

 検討の結果、(2)の方針でTerraform Modulesの構成を考えることにしました。実際、(1)の方針ではサービス・システム毎に特化したTerraform Modulesのため、極力少ない設定でインフラ構築・運用が可能です。しかし、サービス毎のシステム構成の変更に追従してTerraform Modulesをメンテナンスしていく必要があり、メンテナンス面で課題がありました。
 一方、(2)の方針では、サービス・システムの個別の設定・構成に依存せずに全社に展開出来るため、メンテナンス面の課題は小さめでした。また、社内要件やクラウドサービスにより推奨される設定をベースとして作り込めば、インフラ構築・運用における作業負荷を軽減可能だと考えました。結果として、メンテナンス性・利用者の負荷軽減のバランスの取れた(2)の方針が最良となりました。
 とは言え、単にクラウドサービス毎にTerraform Modulesを作ってしまうと、汎用性やメンテナンス性は高められるがサービス・システム毎の最適化には繋がらないため、次の2種類のTerraform Modulesを作成することにしました。

種別 説明 用途例
Component Modules クラウドサービスの単体のインフラリソースに対応するTerraform Modules ELB・ECS・EC2・RDS等のリソース毎にModulesで作成する
Catalog Modules クラウドサービスの複数のインフラリソースに対応するTerraform Modules ELB・ECS、CloudFront・WAF等のリソース群をModulesで作成する

 また、社内のサービス・システムの構成パターンを考えたところ、AWSを利用しているものが大半であり、かつCloudFront・WAF・ELB・ECS・RDS・ElastiCacheを用いた構成が多いため、この様なAWSインフラ構成におけるComponent/Catalog Modulesの開発を優先的に進めることになりました。

GitHub Composite Actions

 社内におけるCI/CDツールの利用状況や、CI/CDツールにおけるGitHub向けの連携機能の充実さを考慮し、GitHub Actionsを利用してTerraform CI/CDのパッケージを作成することにしました。
 GitHub Actionsの処理共通化を調べると、Custom Actions、Composite Actions、Reusable Workflowsのいずれかを用いれば良いことが分かり、処理共通化が容易かどうか、下記を満たす形で運用が可能かどうかを考え、Composite Actionsを採用しました。

  • テクノロジー戦略室のOrganization、開発チームのOrganizationは別々である
  • ライブラリ・テンプレートのRepositoryは、テクノロジー戦略室のOrganization管理下である
  • ライブラリ・テンプレートのRepository、開発チーム向けのRepositoryはPrivateである

GitHub Repository Template

 大半の社内サービス・システムでAWSが利用されているため、Terraform・AWS用のGitHub Repository Templateを優先して作ることにしました。また、開発チームのGitHub Repositoryで最適と思われるものを基準にして、GitHub Repository Templateの構成を考えました。
 Repositoryの生成・設定については、テンプレート内のコード・資料等をスクリプトで書き換える様な仕組みを導入し、テンプレートからTerraform用のRepositoryを低工数で設定出来る様にしました。
 更に、Terraformの管理基盤を構築する際に、Repositoryの設定だけでなく下記の作業も対応する必要があり、下記における設定手順の資料やTerraformの設定ファイルをテンプレートに含め、Terraformの導入における初期作業を全体的に低工数で済む様にしました。

  • Slack通知の初期設定
    • 通知チャンネルの作成
    • Webhook連携の設定
  • Terraformの初期設定
    • Terraform Backendの構築
    • CI/CD用のIAMロールの作成
    • CI/CDの設定作成・有効化
  • クラウドサービスの初期設定
    • 月額予算アラートの設定
    • 監査ログ、セキュリティ検知の設定
    • アラート通知の仕組みの構築

今後の活動

 以上の様に、社内標準のIaCツールの選定と、IaCツールのライブラリ・テンプレートの作成を進めてきました。しかし、現状ではライブラリ・テンプレートにおける開発のルール・フローや全社展開・要望吸い上げの体制が整い切れていないため、今後はこれらを整備してIaC化を推進していく予定です。
 また、現在はAWSを対象にIaCツールのライブラリ・テンプレートを作成していますが、今後はGoogle Cloud、Datadog、GitHub等のAWS以外のクラウドサービスも検討し、ライブラリ・テンプレートの対象範囲を広げていきたいとも考えています。

最後に

 レバレジーズでは、全社のSRE導入に向けて、サービス改善の文化的土俵の構築や開発生産性の向上のための取り組みを手伝って頂けるエンジニアを募集しています。
 SREの文化・体制に興味があったり創っていきたい方や、これからフルスタックエンジニアになっていきたい方は、是非ともご応募をお待ちしております。

TSKaigi2024にプラチナスポンサーとして支援させていただきました

レバレジーズ株式会社 システム本部の檜垣です。

レバレジーズでは、2024/05/11に中野セントラルパークカンファレンスで開催されたTSKaigi 2024で最上位のプラチナスポンサーとしてスポンサーブースを出展しました。

レバレジーズでは、TypeScriptをフロントエンド、バックエンドで幅広く使っていることもあって、日頃の感謝を込めてTypeScriptのコミュニティへの貢献のためにプラチナスポンサーとして支援させていただきました。また、私も微力ながら運営スタッフとして開催をお手伝いしました。

ブース内容

TSKaigiに参加した皆様に楽しんでいただくために、ブースでは、「スクラム開発のための業務効率化支援ツールのAgile Effectのデモ」や「レバ社員を探せ!くじ」などを行いました。

ブースの様子

くじ

楽しく談笑中

agile-effectのデモの様子

記念撮影

たくさんの人に訪れていただき大盛況でした。

agile-effectのデモでは、大変気に入っていただきその場で契約していただいた会社様もいました。

ブースに来てくださった皆様ありがとうございました。

We are hiring

レバレジーズ株式会社ではTypeScript大好きなエンジニアも、それ以外のエンジニアも幅広く募集中です。 もしご興味を持っていただけたなら、こちらのページからご応募ください。

recruit.leverages.jp

TSKaigiを立ち上げて、登壇もしてきました

はじめに

TSKaigiプラチナスポンサーであるレバレジーズ株式会社のテクノロジー戦略室室長 & 一般社団法人TSKaigi Association 代表理事 & TSKaigi2024 Speakerの竹下です。
TypeScriptの言語カンファレンスであるTSKaigi2024が5月11日(土)に中野セントラルパークで開催されました。基調講演にはMicrosoftのTypeScript Product ManagerであるDaniel Rosenwasser様を迎え、37名の登壇者、会場での参加者約400名、オンライン参加約2000名の、大規模イベントになりました。

この記事では、私がTSKaigiを立ち上げた経緯と、登壇者として発表してきた「Step by Stepで学ぶ、ADT(代数的データ型)、モナドからEffect-TSまで」について、紹介したいと思います。

TSKaigiとは

TSKaigiは、TypeScriptをテーマにした、技術カンファレンスです。俗に言語カンファレンスと呼ばれる、特定のプログラミング言語を扱ったカンファレンスで、有名なものではRubyKaigiやPyCon、PHP Conference、ScalaMatsuriなどがあります。(ちなみに私はScalaMatsuriの開催にも理事として関わっていたりします)
運営は、私を含む理事4人を中心に、総勢45名ものボランティアスタッフによって行われました。

ここがすごかったよTSKaigi

初開催でいきなり2400名規模!

技術カンファレンスとしては、日本でも大規模に分類されるイベントです。会場には約400名、オンラインで約2000名の方にご参加いただきました。TypeScriptのイベントとしては現時点で日本一の規模だと思います。初開催でノウハウがない状態から、大きなトラブルもなく無事にイベントを開催できたのは素晴らしいことで、運営を手伝ってくださったスタッフの方々の頑張りの賜物です。感謝の気持ちでいっぱいです。

基調講演はMicrosoft TypeScriptのProductManagerのDaniel Rosenwasserlさん!

言語の開発者というものは普段あまり意識しないかもしれませんが、DanielさんはTypeScript自体を長年にわたって開発してくださっている方です。また、JavaScriptの標準仕様を策定する団体であるTC39にも関わっておられます。TypeScriptやJavaScriptを使うエンジニアにとっては、足を向けて寝られない方です。そのDanielさんが、TSKaigiの基調講演を行ってくれました。

レバレジーズ株式会社を始め38社が協賛!

レバレジーズも最上位のプラチナスポンサーとして協賛しましたが、プラチナスポンサー、ゴールドスポンサー、シルバースポンサー、ブロンズスポンサーをはじめ、コーヒー、ビール、リフレッシュメント、イベントツールなどの特殊スポンサーを含め、合計38社に協賛していただきました。スポンサー募集期限後に開催を知って協賛できなかった企業様も多数おられたので、来年は周知を徹底し、TypeScriptを盛り上げてくださる企業様を増やしていきたいです。

立ち上げ経緯

コミュニティの盛り上がりが、人気に比例していない

TypeScriptの人気はコロナ禍中にもどんどん高まり、開発者の数も増え、使用範囲もフロントエンドに留まらず、バックエンド、インフラ、AI/ML、IoTと非常に幅広くなっています。しかし、私個人の感想にはなりますが、TypeScriptといえばこの人という存在や、日本発のOSSライブラリは、人気や開発者数に対して少ないと感じていました。また、コミュニティ活動も行われている方は数多くおられましたが、その方々が大々的に知られる機会もあまり無いと感じていました。

コミュニティの核となるイベントを作る

TypeScriptの言語カンファレンスは、コロナ禍前にTSConf JPが開催されていましたが、その後中断してしまい、日本では大規模なイベントが開催されていない状態でした。コミュニティが盛り上がらない原因として、コロナ禍も影響し、中核となるイベントやコミュニティがなく、交流の輪が広がっていかないことが挙げられます。
そのような状況の中で、TSKaigiを開催することで、TypeScript開発者に成果を発表してもらう場を提供するとともに、TypeScriptコミュニティの皆さんにどんな人がいて、どんな使い方をされているかを知ってもらう場を提供できると考えました。また、TSKaigiに参加してもらうことで交流が生まれ、そこから交流が続くことでTypeScriptコミュニティ全体の活性化につながると考えました。

団体としてコミュニティの活性化を継続

また、単発イベントではなく継続開催することが、TypeScriptコミュニティの継続した発展に繋がると考え、同時期に同じことを考えていた他の理事と共同で一般社団法人TSKaigi Associationも設立しています。来年以降の開催や、サブイベントの開催も行っていこうと思っていますので、是非この記事をお読みの皆さんご参加下さい。

登壇内容

また、賑やかしのためにセッションの応募したら当選していたので発表も行ってきました。以下が発表スライドです。

スライド

おまけ

この発表では、Effectの導入する意義に焦点を当てて解説していますが、実際の運用では一歩踏み込み、Effectによる関数の細粒度化と副作用分離によるアーキテクチャーレベルの設計も行っています。機会があればそちらも発表したいと思います。

おまけのおまけ

代表理事として、開幕の挨拶もしたのですが、演台の前からはなれて動きながら喋ってたら演台にもどれって怒られました(笑)

オープニングトーク

P.S. 書いててレバレジーズ株式会社のエンジニアとしてなのか、TSKaigiの代表理事としてなのかよくわからなくなってきて、ちょっと混乱した文章になっていますがご容赦下さい。また、TSKaigiの代表理事としての思いなどは、改めてTSKaigiのブログで書きたいと思います。

We are hiring!!!

レバレジーズ株式会社では一緒にサービスを開発してくれるエンジニアを幅広く募集中です。
TypeScriptで開発するだけでなく、コミュニティ貢献もしていきたいという人もウェルカムですし、TypeScriptに触ってないけど興味あるよという人もウェルカムです。 もしご興味ありましたら、こちらのページからご応募ください。

株式会社ビザスク様と設計合同勉強会を開催しました

レバレジーズ株式会社 レバウェル開発部 SREの中村です。
2024/03/13に、設計をテーマに合同勉強会を開催しました。 領域を絞らずに発表いただいたことで、設計について幅広く知見を得られた勉強会になりました。
また、弊社が東京の渋谷に物理出社がメインで、ビザスク社がフルリモートということで Zoomを使用してオンラインでの開催になりました。 この記事では、弊社のエンジニアの発表内容を簡単にご紹介したいと思います。

発表内容

弊社からは、二人が発表しました。


テクノロジー戦略室 室長 竹下

speakerdeck.com

EffectというTypeScriptのライブラリを活用して、IOに関する副作用を分離した設計を実現する方法について発表されています。また、その際にEffectを導入する利点についても紹介されています。


レバテック開発部ITSプロダクト開発グループ PdM兼テックリード 古庄

speakerdeck.com

レバテックにて、新たに構築中のデザインシステム「VoLT」について発表されています。構築プロセス、システム設計や実装例について紹介されています。


We are hiring

レバレジーズ株式会社ではどの領域のエンジニアも幅広く募集中です。 もし今回の勉強会の発表を見てご興味を持っていただけたなら、こちらのページからご応募ください。

勉強会の開催も随時受け付け中です

今回は設計をテーマに合同勉強会を開催しましたが、工程を絞ったものだけでなく、フロントエンド、バックエンド、インフラ、機械学習といったように、様々なテーマで弊社と合同勉強会を開催してくれる企業様を募集中です。ご興味ある企業様がいらっしゃいましたらご連絡いただけると嬉しいです。

LangChain最新バージョンで三大クラウドのLLMをサクッと実装してみる

DALL·Eで生成したLangChainのイメージ画像

  • LangChainの動作確認済みバージョン(2024/3/26時点では最新)
    • langchain: 0.1.13
    • langchain-community: 0.0.29
    • langchain-openai: 0.1.0
    • langchain-google-vertexai: 0.1.1


はじめに

テクノロジー戦略室 AI/MLエンジニアリングチームの稲垣です。
AI/MLエンジニアリングチームでは、レコメンドエンジンの MLOps 基盤の構築や、AWS Personalize などの ML サービスや LLM など生成 AI 活用を、企画から構築まで進めています。


今回は、LangChain の最新バージョン(2024/3/26時点)を使った複数モデルの実装方法について紹介します。

このような実装ニーズは良くあるかと思いますが、案外記事がまだ落ちていないようでしたので記事にしてみました。


現在、社内で LLM を使ったツール開発を行っており、LLM は以下のような複数ベンダー&複数モデルの API を使用しています。

  • GPT-3.5-turbo, GPT-4 (Azure OpenAI Service)
  • Gemini Pro (Google Cloud VertexAI)
  • Claude 2, Claude3 (AWS Bedrock)

それぞれのモデルに対して別個に実装していくことももちろん可能ですが、
API 入力/出力のフォーマット、良くある前処理や後処理、ストリーミングによる出力などの実装方法がモデルごとに異なるケースが多く、
それらを別個に実装していく手間はモデルの数が増えるほど大きくなっていきます。

(実際、anthropic-sdk-pythonによる Claude モデル実装と、google-cloud-aiplatformによる Gemini モデル実装は根本的な箇所でいくつか大きな差異があります。)

このようなモデルごとの実装の差異を吸収してくれるライブラリとしてLangChainがあり、 社内ツールの実装でも LangChain を利用しています。

LangChain:github.com


また、LangChain について最近の動向としては、
2024/1/6 にバージョン 0.0.354 から 0.1.0 へのアップデートがあり、LangChain 初の安定バージョンとなった、というニュースがありました。
(これ以前は破壊的な変更が頻繁に起こったり、公式ドキュメントのクイックスタートの内容が見るたびに変わっていたりしました、、、)

ただし、この 0.1 系へのアップデートにより、LangChain のパッケージの構成について大きな変更があったため、この点についても後半で補足しつつ説明をしていきたいと思います。


複数 LLM の切り替え実装

先に補足事項を記載します。

  • チャットツール等のユースケースではストリーミングによる出力を行うケースが多いかと思いますが、その場合は別途 CallBack 関数を渡す実装が必要になるケースがあるため、今回はストリーミングをオフにしています。
  • 下記のコード例では分かりやすさ重視のためシークレット情報をベタ書きしています。(実際の自社のコードではシークレット情報は AWS Secrets Manager で管理しています。)

AzureChatOpenAI

環境変数AZURE_OPENAI_ENDPOINTOPENAI_API_KEYに対しては、 Azure OpenAI Service から取得した値を設定しています。(参考

import os

from langchain_openai import AzureChatOpenAI


os.environ["AZURE_OPENAI_ENDPOINT"] = https://xxxxxxxxxxxxxx.openai.azure.com/
os.environ["OPENAI_API_KEY"] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
os.environ["OPENAI_API_VERSION"] = "2023-05-15"


chat_model = AzureChatOpenAI(
    streaming=False,
    deployment_name="gpt-4",
    # 必要であれば
    # temperature=0.9,
    # model_kwargs={
    #     "top_p": 0.9,
    # },
)

ChatVertexAI

Google Cloud への認証は下記2種類の方法があります。(参考

  • gcloud や workload identity により実行環境に認証情報を紐づける方法
  • 認証情報の json ファイルの格納パスを環境変数GOOGLE_APPLICATION_CREDENTIALSに設定する方法


今回は後者の方法で実装を行いました。
認証情報の json ファイルの作成方法はこちらのリンクが参考になります。

import os
from langchain_google_vertexai import (
    ChatVertexAI,
    HarmBlockThreshold,
    HarmCategory,
)

# 環境変数に認証情報が入った json ファイルのパスを設定
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "./credential_file_name.json"

chat_model = ChatVertexAI(
    model_name="gemini-1.0-pro",
    streaming=False,
    # Geminiはシステムプロンプトに対応していないため、システムプロンプトを入れる場合はここをTrueにする
    convert_system_message_to_human=True,
    # 適宜要件に合わせて設定してください。今回はブロックが起こりにくい設定(BLOCK_ONLY_HIGH)にしています
    safety_settings={
        HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_ONLY_HIGH,
        HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_ONLY_HIGH,
        HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_ONLY_HIGH,
        HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_ONLY_HIGH,
    },
    # 必要であれば
    # temperature=0.9,
    # top_k=0.9,
    # top_p=32,
)

BedrockChat

Amazon Bedrock へのアクセス権限を持つ IAM ロールが付与された環境で実行するか、
アクセスキー ID とシークレットアクセスキーを環境変数に設定して実行してください。

from boto3.session import Session
from langchain_community.chat_models import BedrockChat

BEDROCK_REGION = "ap-northeast-1"
session = Session()
bedrock_runtime = session.client("bedrock-runtime", region_name=BEDROCK_REGION)

chat_model = BedrockChat(
    streaming=False,
    client=bedrock_runtime,
    model_id="anthropic.claude-v2:1",
    # 必要であれば
    # model_kwargs={"temperature": 0.1, "top_p": 0.9, "top_k": 250},
)

チャットモデルから出力を受け取る

from langchain.schema import (
    AIMessage,
    HumanMessage,
    SystemMessage,
)

messages = [
    SystemMessage(
        content="あなたは江戸時代から続く老舗寿司屋の職人です。質問に対してぶっきらぼうに回答してください。"
    ),
    HumanMessage(content="オススメの寿司ネタは?"),
    AIMessage(content="まぁ、季節によるな。今なら鯖が旨い。"),
    HumanMessage(content="その理由は?"),
]

response = chat_model.invoke(messages)

print(response.content)
# > 鯖はこの時期に脂がのって味が濃くなるんだよ。


やっていることとしては、
使用したい LLM が指定できるクラスAzureChatOpenAI, ChatVertexAI, BedrockChatをそれぞれ import し、それらのクラスのインスタンス化の際に必要な引数や環境変数を設定すれば OK です。

ここまで出来れば、後はモデルごとの実装方法の差異を LangChain がうまく隠蔽してくれるため、

  • API の入力/出力のフォーマット
  • 良くある前処理や後処理
  • ストリーミング時の処理

などを共通化することができ、LangChain の恩恵を受けることができます。


また、パッケージのインストールについての補足事項としては、
LangChain のバージョン 0.1 系へのアップデートに従い、LLM の外部プロバイダーとの統合部分の処理はlangchainパッケージからlangchain_communityパッケージもしくは独立した新パッケージに分離がなされました。

こちらは LangChain 公式の以下の記事でも紹介されています。

blog.langchain.dev

Specifically we made two large architectural changes: separating out langchain-core and separating out partner packages (either into langchain-community or standalone partner packages) from langchain.

(意訳):
具体的には、大きな構造変更を二つ行いました:langchain-core パッケージの分離と、パートナーパッケージの langchain からの分離(langchain-community パッケージに組み込むか、独立したパートナーパッケージとして分離)です。


そのため、上記のコードでは、

  • AzureChatOpenAI: langchain_openaiからインポート
  • ChatVertexAI: langchain_google_vertexaiからインポート
  • BedrockChat: langchain_communityからインポート

としています。

※ 補足:
0.1 系へのバージョンアップでは後方互換性が担保されているので、例えばChatVertexAIであれば以下でも import が可能です。

from langchain.chat_models.vertexai import ChatVertexAI
from langchain_community.chat_models.vertexai import ChatVertexAI

ただし非推奨の warning が出るので、上述のとおり適切なパッケージからの import をおすすめします。


おまけ:
AzureChatOpenAI, ChatVertexAI, BedrockChatともBaseChatModelというクラスのサブクラスになっています。
そしてBaseChatModellangchain_coreパッケージに実装されているため、 ここからも LangChain のコア機能はlangchainlangchain_coreで開発し、外部プロバイダーに依存する機能はlangchain_communityや独自パッケージで開発する、という意図が汲み取れます。



まとめ

LangChain を使った複数 LLM の実装を紹介しました。
レバレジーズでは MLOps 基盤や ML 活用を企画から考え構築までやりたいエンジニアを募集しています! ご興味のある方はぜひ採用サイトをご覧ください!

レバウェルのCM放送後の急増ユーザーを受け止めろ!~API処理速度82倍向上の秘訣~

はじめに

レバレジーズ株式会社 レバウェル開発部 バックエンドチームサブリーダーの山口です。

総合転職サービス「レバウェル」は

  • 転職アドバイザー(転職エージェント)
  • スカウトサービス
  • 求人サイト

を1つのサービスで利用できるアプリケーションです。

2024年2月よりCMを放送中です!

youtu.be

このマス広告を打つために、広告効果によって増加するユーザーとその負荷に耐えることができるかの検討と対策を行いました。

本記事では、私たちがどのような視点で速度改善に取り組んだのか、そしてその結果として特定のAPIの処理速度を82倍向上させた経緯をご紹介します。

レバウェルについて

はじめにレバウェルの基本情報と今回取り組む課題の背景について簡単にご説明します。

技術スタック

今回の内容に関係するレバウェルの技術スタックをご紹介します。

  • 言語
    • TypeScript
  • フレームワーク
    • Next.js, NestJS
  • ライブラリ
    • Apollo Server
  • インフラストラクチャ
    • AWS(ECS, RDS)
    • Vercel
  • API規格
    • GraphQL

導入済みの性能対策

ISR(Incremental Static Regeneration)

レバウェルでは初期リリース時にISR(Incremental Static Regeneration)を採用しました。 対象はSEOの観点で重要かつリアルタイム性が高くないページです。

これによりアプリ全体を再ビルドすることなくデータの変化を定期的にページに反映することができます。

DataLoader

GraphQLはクライアントが必要とするデータを必要な分だけ一度に取得できるという強みがあります。 しかしその一方で、データを取得する際にN+1問題というパフォーマンスに関する問題も抱えがちです。今回はN+1問題に関する詳細な説明は省略しますが、この問題を解決するためにDataLoaderを導入しています。 DataLoaderを用いて各リレーションごとのバッチ処理を行い、SQLの実行回数を削減しています。

増加するユーザーとその負荷に耐えられるか

webアプリケーションにおいて表示速度は離脱率と密接な関係にあり、性能を評価する上で重要な指標となります。 どんなにコンテンツが素晴らしくとも、表示速度が遅いと見てもらうことすらできません。

参考:https://www.thinkwithgoogle.com/marketing-strategies/app-and-mobile/mobile-page-speed-new-industry-benchmarks/

マス広告を打つということは、必然的にユーザー数が短期間で増加します。 この負荷によって性能が悪化すると、ユーザーにプロダクトの価値を提供することができなくなってしまいます。 そのような事態を防ぐべく、速度改善の必要性を判断し、必要な対策を講じることとしました。

速度改善の必要性はどう判断する?

速度改善の必要性があるかどうかの判断基準として以下を定めました。

予想されるAPI実行頻度において性能目標を達成しているか

これを判断するために、以下の2点を定義する必要があります。

  • 予想されるAPI実行頻度
  • 性能目標

これらの数値に基づいて負荷テストを行い、実行結果が性能目標を満たしていなければ速度改善の必要があると判断することができます。

API実行頻度の見積もり

今回はマス広告の効果によるリクエスト数の増加を考慮する必要があります。

実際の計算の流れは以下の通りです。*1

とある集計期間における1分間あたりのリクエストレート(単位:RPM)が5 RPM であった時について考える。

1時間あたりのリクエスト数は以下で表すことができる。
TotalRPH = RPM * 60
つまり300 RPHとなる。

また、集計期間におけるログインユーザー数が50人だった時、 ログインしていないユーザー数をX人とする。 このとき、一人当たりに発生する1時間のリクエスト数は
RPH-per-person = TotalRPH / (50 + X)

と表すことができる。 ただし、今回はより余裕を持った対策を行いたいため、ログインユーザーを分母としてリクエスト数を計算することとする。 つまり一人当たりに発生する1時間のリクエスト数は
RPH-per-person = TotalRPH / 50
となり6 RPHとなる。

この時、広告の掲載によって大量のユーザー増加が見込まれる場合について考える。 TVCMを放映した場合、「CMを認知してもらう」という目的では個人全体視聴率でおよそ500GRPが目安とされている。 *2
GRP500の場合3000万人前後に視聴されるというシミュレーション結果があるため、本検証でもこの数値を使用する。*3

次にCTRが仮に0.2%だとすると約6万人前後がTVCM放映期間中に流入することになる。
TVCM放映期間がスポットCMの契約最短期間である一週間と仮定すると、
1時間当たりの新規流入数 = 60000 / (24 x 7) ≒ 357
増加するリクエスト数(毎分) = (RPH-per-person * 357) / 60
と表すことができる。
この結果 35.7 RPMとなる。

既存のリクエストレートと合算し、性能を担保をすべき最低限のリクエスト数は
41.7 RPM ≒ 0.7 RPS
となる。

性能目標

今回レバウェルでは、以下のことから改善対象APIをp95 1秒以下でレスポンスすることを性能目標として定めました。

  • 主要機能を改善対象とする(後述)
  • 本サイトにメディア的性質がある
  • SEO要件からより速い描画速度が求められる

API実行レートはTVCM配信後に波のようなスパイクが来ることを想定し、見積もりよりかなり余裕を持たせて5 RPS でテストすることにします。

どこを改善する?

主要機能の分析

さて、ここまでで速度改善の必要性を判断するための基準は準備できました。 次にやるべきことは、その基準に基づいて必要性の可否を判断することです。 速度改善の取り組みは時間がかかることが予想されるため、全ての機能について改善することは費用対効果的によろしくありません。 そこでレバウェルでは、まずAPIの実行量を観測し、速度改善に値するものを抽出することにしました。

API実行量の観測

今回はApollo StudioのAPI統計情報から最も実行されているGraphQL Operationを探しました。

Insightsから統計情報を確認します。 リクエストレートを確認してみると、上位2つが多く実行されていることがわかります。 対応する画面を確認したところレバウェルの中核となる部分と対応しており、システム的にこれらの二つが主要機能と言えます。

本記事では最もレートが高かったリクエスト名をtarget(仮)、 それに対応するAPI名をgetTargetInfo(仮)として説明します。

負荷テストによる速度調査

特定した画面およびAPIについて速度改善の必要性があるかを判断します。 判断基準は決定しているため、そちらに従って負荷テストを行います。テストランナーはk6を使用します。

まず先ほど特定したリクエストレートの高いGraphQL Operationを使用している画面について試験を行います。 対象画面を含めた合計4つの画面に仮想ユーザー数100で繰り返しアクセスすることとします。

http_req_duration(p95)が12秒超という非常によろしくない結果です。

次にバックエンドサーバーに対し、画面で要求しているフィールドと全く同一な状態でAPIを実行します。

getTargetInfo(仮)を5 RPSで実行した結果

avg=7.44s min=430.08ms med=8.62s max=9.73s p(90)=9.47s p(95)=9.53s 

これはp95 1秒以下でレスポンスするという性能目標を満たしていないため、改善する必要があると判断しました。

どうやって改善する?

基本的なwebアプリケーションであればSQLが最もボトルネックになりやすい箇所です。 そのためまずSQLに注目することにしました。

以下の流れに従って調査します。

1. ボトルネックとなっているSQLを見つける.
2. そのSQLが遅い原因を理解する.
3. 改善する.
4. 改善したSQLを測定する.

どういったSQLが実行されているか

対象のAPIを実行した時、どのようなSQLが実行されるのかをチェックします。 ここで明らかな問題(N+1問題や初歩的なWHEREでの絞り忘れなど)があれば、まずはそれを解決できるからです。

今回は以下のようなテーブル構成とGraphQLのqueryを例とします。

query target($getTagetInfoId: Int!) {
 getTagetInfo(id: $getTagetInfoId) {
   id
   name
   status
   targetSkills {
     skillId
     level
     skill{
       id
       name
     }
   }
 }
}

targetテーブルに連なるリレーションはTypeORMのLazy Relationsによって解決します。

この場合、要求されたリレーションのフィールド1つにつき1件のSQLが実行されます。 この例の場合、以下のように少なくとも3回実行されるイメージです。

1. 指定されたIDを持つターゲット情報を取得する。
これはgetTagetInfoフィールドに対応します。

SELECT * FROM target WHERE id = $1;

2. そのターゲットに関連するtargetSkillsを取得する。
これはtargetSkillsフィールドに対応します。

SELECT * FROM target_skills WHERE target_id = $1;

3. 各targetSkillsエントリに関連するskillを取得する。
これはskillフィールドに対応します。 targetSkillsの各エントリに対して1つのクエリが実行されるため、このステップでのクエリ数はtargetSkillsのエントリ数に依存します。

SELECT * FROM skills WHERE id = $1;

実際にレバウェルの該当ページを開いてGraphQLリクエストを発生させたところ、およそ100件を超えるSQLが実行されていました。

これ自体はGraphQLの設計思想上、「要求されたものだけを取得する」ということで間違っていません。また、前述(導入済みの性能対策)の通りDataLoaderを用いた各リレーションごとのバッチ処理は行っています。 しかし該当ページは描画要件の都合により、取得しなければならないフィールドが多く、DataLoaderによる性能改善には限界がありました。

約100テーブルに及ぶ膨大なリレーション情報が必要となると、データ解決手法によってはパフォーマンス問題が発生する恐れがあります。 またコネクションプールの枯渇、ネットワークコストの増加による負荷増の問題も考えられます。

Slow Queryはあるのか

次にSlow Queryがあるかを調査します。 仮に実行時間の大半を占めるようなSlow Queryがあり、それを解消すれば良いなら100件のSQLを実行する形のままでも目下の障害にはならないからです。

今回はpostgresのpg_stat_statementsモジュールを使って分析しました。
対象APIを呼ぶページを開き、以下のSQLでSlow Queryを抽出します

SELECT * FROM pg_stat_statements order by total_time desc limit 100;

今回は個別のクエリは軽いようで、 一番かかっているもので26msほどでした。 これはindexや個別のSQL最適化が意味をなさず、100件の分割されたクエリを何らかの方法でまとめなければならないことを意味しています。

改善方針決定

次は100件のSQLを1つのSQLにまとめるなら、どのようにすれば良いのか考えます。 もちろん単純に100テーブルをJOINしてしまうと結果セットがデカルト積となり、爆発的な量となってしまうので実現不可能です。

そこで今回は以下の点に注目しました。

  • それぞれのSQLには複雑な条件がない。単純な外部キー結合がメイン
  • 結果セットの多さが問題

ここから考えられる対処法には以下の2つがあると考えました。

1. テーブル設計を変える
2. SQL上のテクニックで結果セットの数を削減する

1の方法は最も高品質なものができる解決法ですが、今回対象となるテーブルはレバウェルの根本となっているため、リプレイスに近い形になってしまうことから見送りました。2の方法はあまり見ない方法ですが、今回のケースではJSONB_AGG集約関数とJSONB_BUILD_OBJECT関数を用いることで結果セットを減らせそうです。 一方でSQLが複雑なものとなり保守性が低下してしまうのがデメリットです。
今回はメリット・デメリットを総合的に判断し2の方法を採用することにしました。

実装

100件のSQLを1つのSQLにまとめる

結果セット数を抑えつつ100件のSQLを1つにまとめるために、大きく4つのSQLの文法を使用しました。

  • Common Table Expressions

postgresではWITH ASの構文で表されます。一時的な名前付き結果セット、つまりサブクエリの結果を生成するために使用されます。主な利点は、複雑なクエリをより読みやすくかつ管理しやすくすることです。また、同じサブクエリを一度書いてそれを再利用することができます。
参考:https://www.postgresql.jp/docs/9.5/queries-with.html

  • LATERAL

LATERALを付与したサブクエリはそれより前のFROM項目を参照できるようになります。今回はLEFT JOIN LATERALの形で使用しました。これによってサブクエリが外部クエリの行に依存する場合に、それぞれの行に対して異なる結果セットを生成できます。そして、LEFT JOINの性質上サブクエリが結果を返さない場合、nullとして処理されます。
参考:https://www.postgresql.jp/document/9.6/html/queries-table-expressions.html

  • JSONB_BUILD_OBJECT

キーと値のペアからJSONBオブジェクトを作成するための関数です。この関数は任意の数の引数を取り、それらを交互にキーと値として扱います。行のデータをJSON形式で出力する必要がある場合など、データを柔軟に扱いたい時に便利です。
参考:https://www.postgresql.jp/document/13/html/functions-json.html

  • JSONB_AGG

引数を受け取り、JSONB配列に集約する関数です。
参考:https://www.postgresql.jp/docs/9.5/functions-aggregate.html

詳細な内容はPostgreSQL公式をご参考ください。

実装SQLはこのような形になります。

WITH
r_target AS (
   SELECT * FROM target t
   WHERE t.id = $1 AND t.status = 'active'
),
s AS (
   SELECT
       ts.target_id,
       JSONB_AGG(
           JSONB_BUILD_OBJECT(
               'skill', s.obj,
               'level', ts.level
           )
       ) as target_skills_info
   FROM target_skills ts
       INNER JOIN LATERAL(
           SELECT
               JSONB_BUILD_OBJECT(
                   'id', s.id,
                   'name', s.name
               ) AS obj
           FROM skill s WHERE s.id = ts.skill_id
       ) s ON true
   WHERE ts.target_id = (SELECT id FROM r_target)
   GROUP BY ts.target_id
)
SELECT * FROM r_target
LEFT JOIN s ON s.target_id = r_target.id

実行結果イメージ

id name status target_id target_skills_info
1 hoge active 1 [{‘skill’: {‘id’: 1 ,‘name’: ‘skill1’}, ‘level’: 5}, … ]

実際には上記の対応を全てのリレーションに適用し、そのSQLを用いることで効果の検証を行います。

補足

nullハンドリング

上述のSQLでLATERALを使用した理由としてネストしたオブジェクトのnullハンドリングがあります。 例えば、

-- v.hogeは存在しない
SELECT JSONB_BUILD_OBJECT(
    'v_id', v.id, 'hoge',
     JSONB_BUILD_OBJECT('name', h.name)
 ) FROM v LEFT JOIN hoge h ON h.id = v.hoge_id

この結果は{v_id: x, hoge: {name: null}} となります。

この時に、GraphQLで「v.hogeはnullableだが、hoge.nameはnot nullable」のような設定をしている場合は少々困ってしまいます。

そのため以下のようにしてnullハンドリングを行いました。

-- v.hogeは存在しない
SELECT JSONB_BUILD_OBJECT(
    'v_id', v.id, 'hoge', h.obj
) FROM v LEFT JOIN LATERAL(
    SELECT JSONB_BUILD_OBJECT('name', h.name) AS obj
    FROM hoge h 
    WHERE h.id = v.hoge_id
) AS h ON true

LATERALを使用することで、サブクエリが各vの行に対して独立して評価されます。そしてLEFT JOINであるため、h.id = v.hoge_id を満たさない場合はobjがnullとして結合されます。 従って{v_id: x, hoge: null}となり、一般的にイメージされるnullableなオブジェクトになります。

設計方針

今回選択した手法はGraphQLの大きな強みである「不要なデータフェッチを防ぐ」にやや反するものとなっています。 つまりGraphQLとSQLが分離できておらず、オーバーフェッチが発生し得る設計となっています。 その上で本方針を選択した理由として以下があります。

  • 該当APIの使用目的が限定されており、実際にはオーバーフェッチが発生しない
  • 工数の都合によりEager Loading的な設計を選択せざるを得なかった

プロダクト全体としてはLazy Loadingを使用し「クライアントが必要とするデータを必要な分だけ取得する」という設計方針で実装されています。

対策後の計測

API処理速度の検証

対策の効果を検証するため、上記のSQLを適用した新しいAPIに対して負荷テストを行います。 条件は前回と同様に5 RPS, 同一要求フィールド、同一のレコードです。

avg=59.98ms min=36.26ms med=50.89ms max=201.09ms p(90)=96.25ms p(95)=115.55ms

以前の結果

avg=7.44s min=430.08ms med=8.62s max=9.73s p(90)=9.47s p(95)=9.53s

レスポンスタイム(p95)で約82倍の高速化に成功しており、かなり改善をすることができました。

おわりに

以上がレバウェルにおける速度改善の取り組みとなります。 このような性能改善の取り組みは、コストなどの兼ね合いから最も理想的な改善策を選択できないこともあると思います。 しかしながら、状況に応じて最適な対策を打つことで高い効果を得ることができます。

本記事が少しでも参考となれば幸いです! 最後までお読みいただきありがとうございました。

現在、私たちと一緒に社会課題に挑戦するエンジニアを募集中です! ご興味のある方はぜひ採用サイトをご覧ください!

*1:実際に使用したリクエストレートなどの数値は計測値を使用しています。 今回は説明の都合上、仮の値を使用しています。

*2:GRPとは「Gross Rating Point(グロス・レイティング・ポイント)」の略語 一定期間に放送されたテレビCMの視聴率を合計したもの≒何回視聴されるか

*3:500GRPもしくは1,000GRPのCM出稿をしたら、何人に見られるのか?