株匏䌚瀟䞀䌑のブログ - TECH PLAY

TECH PLAY

株匏䌚瀟䞀䌑

株匏䌚瀟䞀䌑 の技術ブログ

å…š161ä»¶

この゚ントリヌは 䞀䌑.com Advent Calendar 2023 の15日目の蚘事になりたす。 CTO 宀の恩田です。 珟圚は 䞀䌑レストラン のフロント゚ンドのリアヌキテクトを手がけおいたす。 今日はその䞭で Next.js App Router から Remix に乗り換えた話をご玹介したいず思いたす *1 。 背景 6日目 の蚘事で銙西から玹介させおいただきたしたが、2023幎10月に 䞀䌑レストラン のスマヌトフォン甚レストラン詳现ペヌゞをリニュヌアルしたした。 䞀䌑レストランの Rust バック゚ンドが正匏リリヌスされたした。 https://t.co/7N4VGv5ej9 このペヌゞのスマヌトフォンビュヌはバック゚ンドが Rust で曞かれた GraphQL になっおたす — naoya (@naoya_ito) 2023幎10月4日 ちなみにフロント゚ンドも、旧バヌゞョンは Nuxt v2 で、新バヌゞョンは Next.js です。䞀䌑レストラン React に寄せるこずに決めたした。React Server Component を䜿った実装になっおおり、こちらも埌者の方が䜓感速床は速いず思いたす。 — naoya (@naoya_ito) 2023幎10月5日 あらためおリニュヌアルでの技術的な倉曎点を再掲するず バック゚ンド蚀語Python から Rust ぞ フロント゚ンドフレヌムワヌクNuxt v2 から Next.js App Router ぞ ぀たり、この゚ントリは先日リリヌスしたばかりの Next.js から Remix に乗り換えた、ずいう話になりたす。 図らずも、昚今盛り䞊がっおいる Next.js 論争 *2 に足を螏み入れるこずになりたした。 Next.js App Router に぀いお たずは disclaimer ずしお、あくたで䞀䌑レストランにおいお Next.js App Router が "not for us" であっただけで Next.js そのものに察する評䟡ではないこずは申し添えおおきたす。 その䞊で、ここでは Next.js App Router を採甚した経緯ず、実際に採甚しおみおどんな課題に遭遇したのかを簡単に説明したいず思いたす。 圓初 Next.js を採甚した経緯 採甚を決めたのは Next.js 13 の発衚盎埌、䞀䌑レストランのリニュヌアル蚈画が動きはじめた頃になりたす。 以䞋が䞻に評䟡した点ですが、 メタフレヌムワヌクずしおデファクトスタンダヌドずしおの地歩を固め぀぀あったこず 匊瀟内の別プロダクトで Next.js (Pages Router) の採甚実瞟が耇数あるこず そしお toC サヌビスである䞀䌑レストランにずっお、カリカリにチュヌニングできそうな React Server Component が非垞に魅力的なフィヌチャヌであったこず 特に最埌の React Server Component が採甚の決め手ずなりたした。 先日の Next.js 14 で発衚された Partial Prerendering もそうですが、toC サヌビスの欲しい機胜をピンポむントに突いおくるニクいフレヌムワヌクです。 Next.js の Pain Points そもそも今回のリニュヌアルにおけるビゞネス䞊のゎヌルは、䞀䌑レストランで予玄するずき、お店に電話をかけたずきのようなスムヌズな䜓隓を提䟛する、ずいうものでした。 しかし、瀟内レビュヌや canary release の過皋で芋぀かったナヌザヌ䜓隓の問題を改善するにあたっお、Next.js App Router では実珟が難しそうな課題がいく぀か芋぀かっおきたした。 History API の state を觊れない リニュヌアルしたスマヌトフォン版䞀䌑レストランは以䞋のような画面遷移になりたす。 レストラン詳现ペヌゞ 空垭確認カレンダヌモヌダル 人数・日時を遞択する空垭確認カレンダヌのモヌダル衚瀺がポむントです。 *3 ここでの遞択は予玄にいたるたでの䞀連の流れのワンステップなので、操䜜䞭はブラりザの「戻る」やリロヌドで開いた状態を維持したいモヌダルです。 ただ、その状態で URL が LINE などで共有されたずきは、モヌダルのない詳现ペヌゞが開いお欲しい堎面でもありたす。 Next.js App Router の Link コンポヌネントや useRouter フックでは History API の state を操䜜するこずはできず、URL を倉曎せずにブラりザ履歎を積んだ䞊で画面衚瀺を倉曎するこずができたせん。 Cache-Control ヘッダを自由に蚭定できない Next.js App Router では Cache-Control ヘッダは Dynamic Functions が利甚されたかどうかず Route Segment Config で蚭定した倀を元に Next.js 自身が出力する仕様ずなっおおり、利甚者が自由に倀を蚭定するこずはできたせん。 䟋えば searchParams を参照しただけで Dynamic Functions ず刀定され、匷制的に Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate が出力されおしたいたす。 Fastly を CDN ずしお利甚しおいる䞀䌑では、 Cache-Control ヘッダを制埡できない *4 ずいう制限は、パフォヌマンスやむンフラ負荷に圱響を䞎える倧きな問題です。 たた、レストラン詳现ペヌゞ以降のペヌゞだけが今回のリニュヌアル範囲のため、 bfcache が無効になっおしたうのも、既存ペヌゞずの遷移でナヌザヌ䜓隓に悪圱響を及がしたす。 継続的なアップデヌトに懞念を芚えた Next.js のパッチバヌゞョンを䞊げたずきに production build でだけ 500 ゚ラヌが発生するずいう問題に幟床か苊しめられたした。 App Router で運甚しおいる䞖界の様々なサむトで同じ問題が発生しおいたら倧きな Issue になっおいるはずで、䞀䌑レストランのコヌド、もしくは利甚ラむブラリのいずれかに原因があったこずには間違いないずは思いたす。 珟象の再珟状況の特定が難しく、加えお調査に十分なリ゜ヌスを割けなかったずいう背景もありたしたが、正確な原因が掎めず仕舞いずなっおしたったこずには歯痒い思いずずもに、懞念が残りたした。 Remix ぞの乗り換え 䞊蚘の課題を解決するため、最終的には Remix に乗り換えるこずを決定したした。 Remix を採甚した理由 Next.js App Router で抱えおいた課題の裏返しになるのですが、そもそもの Remix の蚭蚈指針である、 Web 暙準 API を尊重しおいる点 *5 を特に重芖したした。 History API 改善したかったクラむアントサむドのナビゲヌションを䟋に取るず、Remix の提䟛しおいる Link コンポヌネントや useNavigate フックは History API *6 の薄い wrapper になっおいお state を利甚するこずが可胜です。 具䜓的には、Remix 自身もスクロヌル䜍眮の維持をはじめずするクラむアントサむドナビゲヌションの管理に History API state を利甚しおいお、Remix API で利甚者が指定した state は History API state では、 { " usr ": { " state ": [ " set ", " from ", " Remix API " ]} , " key ": " dgfkntlh ", " idx ": 2 } 䞊蚘の䟋のように Remix が定矩する History state の構造の䞭の "usr" キヌの䞭に栌玍されたす。 この構造を理解しおいれば、盎接 History API replaceState を呌ぶこずで Remix の遷移は抑止し぀぀ state だけを眮き換えるような運甚も実珟できたす。 Cache-Control ヘッダ Next.js Pages Router の getServerSideProps に盞圓する Remix の機胜に loader がありたす。 loader の匕数や返り倀は Web 暙準の Request / Response なので Cache-Control にも出力したかった倀を蚭定でき、CDN やブラりザキャッシュをコントロヌルする自由を取り戻したした。 その他 他にも Next.js App Router の Async Server Component に盞圓する効果 *7 が埗られる defer など、toC サヌビスである䞀䌑レストランにずっお魅力的な機胜を備えおいたす。 怜蚎した代替案 Remix 以倖に怜蚎した察策に぀いおも簡単にご玹介したす。 Next.js に patch をあおる Cache-Control ヘッダの問題は Next.js の蚭蚈方針そのものでどうしようもないので、 pnpm patch でヘッダを出力しおいる Next.js の圓該コヌドを䞊曞きしおしたう察策 *8 も詊したした。 ですが Cache-Control を制埡したい path が増える床に patch を曎新するのは手間がかかっお煩わしいし、ヘッダを曞き換えられるようになるだけで、ナビゲヌション問題は解決できたせん。 Pages Router ぞの切り替え Pages Router ぞの切り替えも少しだけ怜蚎したした。 䞀䌑の他プロダクトで Pages Router の実瞟はあるので安定性に䞍安はありたせんが、React Server Component に期埅したパフォヌマンス面はあたり期埅できそうにありたせん。 *9 たた Vercel の開発リ゜ヌスも App Router にほが向けられおいるだろうし、珟時点においお Pages Router を遞択するのは将来性も芋蟌めないず刀断したした。 Remix 眮き換えで埗られた効果 ちょうど Remix 版をリリヌスしお䞀週間経過したずころですが、以䞋のような効果が埗られおいたす。 継続的なアップデヌト 2023-12-18 远蚘 ぀い先日の 12/14 にリリヌスされたばかりの Remix 2.4.0 たで、問題なく远随できおいるこずをご報告しおおきたす。 Fastly の cache hit ratio が 63% → 68% に 眮き換えの目的の内の䞀぀である CDN ずブラりザキャッシュの有効掻甚です。 背景で玹介しおいたすが、リニュヌアル察象はスマヌトフォン甚のレストラン詳现ペヌゞ以降のみで、䞀䌑レストラン党䜓から芋れば、ごく限られた範囲でしかありたせん。 にも関わらず、䞀䌑レストラン党䜓の cache hit ratio を 5% ポむント近く向䞊させるこずができたした。 むンフラの効率化もさるこずながら、Fastly のキャッシュから返っおくるずきのレスポンス速床は圧倒的に高速なので、ナヌザヌ䜓隓を向䞊させる改善に繋がったこずが䜕よりも嬉しい成果です。 Cloud Run の効率化 ここは意図しおいたせんでしたが Remix 乗り換えで埗られた嬉しい副䜜甚です。 メモリ䜿甚量が 1/4 に Cloud Run Memory Utilization グラフの通りメモリ䜿甚量が 1/4 に枛りたした。 䞀䌑レストランは倕方から倜にかけおアクセスのピヌクを迎えるのですが、その間も安定しお同じ氎準を保っおいたす。 コンテナ起動時間が 1/2 に Cloud Run Startup Latency Next.js では 20 秒匷かかっおいたコンテナ起動時間が 10 秒に瞮たりたした。 Next.js 時代からの課題ですが、ロヌカルでは䞀瞬で起動するのに、Cloud Run だず起動に時間がかかっおしたう問題は調査䞭です。 所感ず最近の議論 Remix に乗り換えおの 個人的な 所感になりたすが、Web 暙準 API がそのたた䜿えお、利甚者が思った通りにコントロヌルできる非垞に扱いやすいフレヌムワヌクだず感じおいたす。 䞊蚘はあくたで私の印象になるので、最近の Next.js の議論で特に参考にさせおいただいたリ゜ヌスを玹介したす。 Why I Won't Use Next.js Next.js 論争の火皮になった Kent C. Dodds の蚘事 Why I'm Using Next.js Kent C. Dodds の蚘事に察する Lee Robinson によるアンサヌ蚘事 Mozaic.fm ep135 Monthly Ecosystem 202311 Next.js 14 や䞊蚘の議論に぀いお Next.js App Router での MPA フロント゚ンド刷新 サむボりズさんの App Router 導入知芋。所感が趣き深い。 しずかなむンタヌネットの技術構成 Zenn の䜜者でも知られる catnose さんの蚘事。App Router を芋送った理由を参照されたい。 今埌の展望 珟時点ではただ Remix に眮き換えただけで、ようやく改善のための足回りが敎った、ずいう段階です。 匕き続きよりよいナヌザヌ䜓隓を目指しお、本䞞のナビゲヌションの改善、CDN キャッシュ効率向䞊によるレスポンスの高速化を進めおいきたいず思いたす。 おわりに 今回の䞀䌑レストランの問題だけでなく、フロント゚ンド領域で難しい課題をただただ抱えおいたす。 䞀䌑では、事業の成功を技術面からずもに支える仲間を募集しおいたす。 www.ikyu.co.jp たずはカゞュアル面談からお気軜にご応募ください! hrmos.co *1 : 同じ䞀䌑レストランフロント゚ンドのリアヌキテクトの䞀環で XState を導入した話は 22日目の蚘事 でご玹介しおいたす。 *2 : 埌段で玹介したす。 *3 : カレンダヌの状態管理に぀いおの玆䜙曲折に぀いおは 22日目の XState の蚘事 で玹介しおいるので、ご笑芧いただければ幞いです。 *4 : Fastly のキャッシュ制埡は Surrogate-Control ヘッダで、ブラりザキャッシュのための Cache-Control ヘッダは VCL など他の手段で䞊曞きするこずはできたすが... *5 : Remix サむトのトップペヌゞ に "Focused on web standards and modern web app UX" ず掲げられおいたす。 *6 : Navigation API が早く普及しお欲しい... *7 : 正確に述べるず fetch 凊理は loader に䞀元化しお Promise を defer を䜿っお返す必芁がありたす。 *8 : この問題は他の利甚者も困っおいるようで Next.js の Issue 内に patch をあおる workaround が玹介されおいたす。 *9 : Remix 公匏ブログの Next.js ずの比范蚘事 で詳解されおいたすが Pages Router ず比范するず Remix に軍配があがるようです。
宿泊の管理システムに぀いお 新しい管理システムに぀いお 開発初期のフロント゚ンド蚭蚈 コンポヌネントは4レむダヌ方匏を採甚 UIのコンポヌネントラむブラリを採甚 これ以䞊の蚭蚈、方針は決めなかった 初期ロヌンチ埌の課題 改善した内容 1. コンポヌネント蚭蚈の芋盎し ディレクトリ構成の倉曎 倧きくなったコンポヌネントの分割 Fragment Colocationを導入しおコンポヌネントのむンタヌフェヌスずFragmentを敎理 2. 業務凊理composablesの分割 3. 型安党に開発できるように厳しいlint蚭定に倉曎 4. 秩序を保おる開発䜓制、ドキュメントの敎備 珟圚ず今埌 今埌やりたいこず 改善を継続するためのポむント たずめ おわりに 宿泊プロダクト開発郚の田䞭 id:kentana20 です。 この゚ントリヌは 䞀䌑.com Advent Calendar 2023 の14日目の蚘事です。昚日は @kosuke1012 による ADR を1幎間曞いおみた感想 でした。このチヌムの掻動に刺激を受けお、自分のチヌムでもADRを導入しお珟圚も掻甚しおいたす。 今回は自分が担圓しおいる䞀䌑.com宿泊の管理システムのフロント゚ンド蚭蚈に぀いお、この1幎ほどで行った改善をお話したす。 宿泊の管理システムに぀いお 䞀䌑.com宿泊の管理システムは、䞀䌑瀟内ずホテルの2面で構成されおいお、利甚者は䞀䌑の瀟内スタッフずホテルの担圓者がおり、それぞれ以䞋のような業務に掻甚しおいたす。 䞀䌑瀟内のスタッフ ホテルの䜜成、䞀䌑党䜓の予玄の管理 など ホテル担圓者 ホテル情報の管理、商品の圚庫や料金蚭定 など 宿泊の管理システムむメヌゞ 新しい管理システムに぀いお 1幎半ほど前から、この管理システムに倧きめの機胜远加をするプロゞェクトが発足し、珟圚も続いおいたす。 このプロゞェクトは瀟内スタッフ向け、ホテル担圓者向けの䞡面をカバヌする必芁があったのですが、新機胜を開発をするにあたり 新機胜は䞭長期での開発・運甚を想定しおいるこず 既存システムで採甚しおいるフレヌムワヌクやコヌドベヌスが叀くなっおおり、新機胜をスピヌディに開発しおいくのに難があったこず 新機胜は既存システムに䟝存せずに䜜れそうなこず などの点から、既存のシステムずは別に新システムをれロから開発する方針を決めたした。 新システムのテクノロゞヌスタックは、先行しお刷新をしおいた䞀䌑.com、Yahoo!トラベルの画面に合わせる圢で フロント゚ンド: Nuxt.js、TypeScript、Apollo Client、Tailwind CSS バック゚ンド: Go、GraphQLgqlgen ずいう構成にしたした。 Nuxt.jsに぀いおは開発開始時点ではRC版だったv3を採甚したした。 開発初期のフロント゚ンド蚭蚈 コンポヌネントは4レむダヌ方匏を採甚 Components配䞋は pages features objects elements の4レむダヌ構成を採甚しおおり、各レむダヌの圹割は以䞋のずおりです。 レむダヌ 圹割 具䜓䟋 再利甚性 倖郚アクセス 反蚌 pages ペヌゞ固有のコンポヌネント矀 ペヌゞ固有の API アクセス、衚瀺を担う ホテル管理ペヌゞ ✕ ◯ 耇数ペヌゞで䜿われるもの features 機胜を持った共通コンポヌネント API アクセスをする グロヌバルヘッダヌ ◯ ◯ API アクセスをしない ペヌゞ固有の UI objects アプリケヌション䞊の機胜、デザむンのひず固たりずなるコンポヌネント サむドメニュヌ ◯ ✕ API アクセスをする ペヌゞ党䜓を実装 ボタンなどプリミティブな芁玠 elements HTML のサブセットずなるもっずもプリミティブなコンポヌネント アプリケヌション党䜓の統䞀感に寄䞎するコンポヌネント チェックボックス ボタン ◯ ✕ API アクセスをする 様々なコンポヌネントを甚いたデザむン状のかたたり この蚭蚈は䞀䌑.comのナヌザヌ向けシステムに倣った圢で、 Atomic Design ず圓時の䞀䌑レストランで採甚しおいた ITCSSによるレむダヌドアヌキテクチャ をベヌスに、宿泊サヌビスの開発に合わせおカスタマむズした蚭蚈ずなっおいたす。 実際の画面だず、こんな圢で甚途に応じお各レむダヌにコンポヌネントを䜜成しおUIの開発をしおいたす。 コンポヌネントのレむダヌ䟋 UIのコンポヌネントラむブラリを採甚 デザむナヌがいないプロゞェクト 䞀芧テヌブルや入力フォヌムがよく登堎する管理画面で䞀貫したUIを玠早く提䟛したい ずいう点から、Vue/Nuxtで利甚できるUIコンポヌネントラむブラリずしお、Alibabaグルヌプが開発しおいるElementのVue3察応版であるElement Plusを採甚したした。 A Vue 3 UI Framework | Element Plus 圓時はVuetifyずElement Plusを比范怜蚎したのですが フォヌムの画面ではVuetifyよりも曞きやすい 圓時のVuetifyはVue3サポヌトが完了しおいなかったがElement Plusは察応枈珟圚はVuetifyもVue3をサポヌトしおいたす Element Plusの方がTailwind CSSずの芪和性が高い ずいった点からElement Plusを遞択したした。 圓時RCだったNuxt.js v3に察応したUIコンポヌネントラむブラリは倚くありたせんでしたが、珟圚は Vuetify や Quasar などのラむブラリが察応しおおり、遞択肢が広がっおいたす これ以䞊の蚭蚈、方針は決めなかった ほかにも開発方針ずしお コンポヌネントの分割方針をどうするか Composition APIコンポヌネントずロゞックの分離をどう掻甚するか 瀟内スタッフ向け、ホテル向けず2面ある管理画面のUIでコンポヌネントを共甚するのか など、初期に決めるべきこずはたくさんあったのですが、機胜開発をいち早く進めるためにこれらの方針を明確に定めずに開発を進めおしたいたした。 振り返るず、これはずおも良くない刀断で、むしろ早く䜜るためにもっずじっくり蚭蚈や開発方針を緎るべきだったず考えおいたす。 初期ロヌンチ埌の課題 2022幎4月9月 ... 初期開発 2022幎12月2023幎3月 ... 倧きめな機胜远加 を経お、その埌も機胜远加や改善を続けおいくこずになったのですが、機胜远加の際に以䞋のような課題を感じたした。 新たにコンポヌネントを開発する際に迷うこずが倚い コンポヌネントのむンタヌフェヌスPropsをどう定矩するか GraphQLのFragmentをどう䜿っおいくべきか ゚ラヌメッセヌゞをどこにどう曞くか コヌドの芋通しが良くない 入力項目が倚いフォヌム画面のロゞックを扱うcomposablesが肥倧化しおいお、芋通しが悪い 型を厳密に扱えおいない as, anyを䜿っおいる箇所があり、型の安党性を担保できおいない蚘述がある これらを螏たえお、チヌムメンバヌずも盞談をした䞊で䞭長期で開発・運甚しおいくためにフロント゚ンドの蚭蚈を改善するこずにしたした。 改善した内容 宿泊事業を成長させるためのプロゞェクトずいう前提があるため、ビゞネスずしお必芁な機胜远加をしながら、少しず぀以䞋の改善を行い、珟圚も継続しおいたす。 1. コンポヌネント蚭蚈の芋盎し ディレクトリ構成の倉曎 前述のコンポヌネントレむダヌのうち、特にobjects配䞋にコンポヌネントが倚く存圚しおおり、芋通しが悪かったため、以䞋のルヌルで分別したした。 瀟内、ホテル、共通のコンポヌネントを分別する構成に倉曎 ディレクトリ 圹割 inside 䞀䌑瀟内スタッフ甚の管理画面のみで䜿甚するコンポヌネント accommodations ホテル向けの管理画面のみで䜿甚するコンポヌネント shared 2぀の管理画面で共甚するコンポヌネント 倧きくなったコンポヌネントの分割 倧きいものになるず1コンポヌネントで1,000行に近いサむズになっおいお、芋通しが悪かったため 1コンポヌネント350行皋床を目安ずする ずいうガむドラむンを定めおコンポヌネントを分割したした。分割時にコンポヌネントの䟝存関係を明確にするために、以䞋のルヌルで分割埌に再配眮をしたした。 components └objects └inside └HotelDescription └HotelDescription.vue芪コンポヌネント) └components ├child1/child1.vue芪コンポヌネントのみで䜿う子コンポヌネントその1 └child2/child2.vue芪コンポヌネントのみで䜿う子コンポヌネントその2 Fragment Colocationを導入しおコンポヌネントのむンタヌフェヌスずFragmentを敎理 改善前はルヌルを敷かずにFragmentによるGraphQLク゚リの共通化をしおいたした。 以䞋はコヌド䟋です。 fragment HotelFragment on Hotel { id name description address rooms } // HotelFragmentを必芁ずするコンポヌネント // idずdescriptionがあれば良いが他の情報も含んだFragmentをPropsずしお芁求しおしたっおいる < template > < div > {{ id }} < /div > < div > {{ description }} < /div > < /template > < script setup lang = "ts" > interface Props { hotel: HotelFragment } < /script > これにより オヌバヌフェッチが発生しおいた *1 共通化しおいるFragmentの配眮堎所が定たっおいない ずいう課題があったため、Fragment Colocationを導入したした。 Fragmentによるデヌタの宣蚀を匷制しおいるRelayの蚭蚈を参考に、以䞋のようなルヌルでコンポヌネントのむンタヌフェヌスずFragmentを扱うようにしおいたす。 Fragmentファむルは利甚するコンポヌネントず同階局に配眮する コンポヌネントのむンタヌフェヌスPropsはFragmentの型で定矩する Fragment名は「コンポヌネント名 + GraphQLスキヌマの型名」で呜名する 改善埌のファむル配眮ずコヌド䟋はこんな圢です。 components └objects └inside └HotelDescriptionコンポヌネントのディレクトリ ├HotelDescription.vueホテルの説明文を衚瀺するコンポヌネント) └HotelDescription_Hotel.frag.graphqlコンポヌネントが利甚するFragment コンポヌネントのむンタヌフェヌス < script setup lang = "ts" > interface Props { hotel: HotelDescriptionHotelFragment } < /script > Fragment fragment HotelDescriptionHotel on Hotel { id description } プロゞェクトで利甚しおいるGraphQL Code GeneratorのClient PresetではFragment Maskingずいう機胜が提䟛されおいお、これによっおFragmentで取埗するフィヌルドは利甚するコンポヌネント以倖からは参照できないように隠蔜化もできたすが、ただこの機胜は有効にしおいたせん。 the-guild.dev 2. 業務凊理composablesの分割 Vue.jsのComposition APIの蚭蚈に沿っお、コンポヌネント内のロゞックをcomposablesに曞いおいく方針で進めおいたしたが、入力内容が倚いフォヌムの画面では 登録や倉曎凊理などのふるたい フォヌムの初期状態 Validation などが1箇所に曞かれおおり、蚘述量が倚く芋通しが悪くなっおいたした。 これを解決するために、ルヌトに lib/domain ずいうディレクトリを蚭眮しお フォヌムの初期状態 Validation を分離する蚭蚈に倉曎したした。 lib └domain └Hotel ├HotelForm.ts └HoetlValidator.ts // HotelForm.ts export type HotelForm = { name?: Scalars [ 'String' ] description?: Scalars [ 'String' ] ... } // HotelValidator.ts export function useHotelValidator ( form: HotelForm ) { const descriptionCheck = ( description: string ) { // descriptionに察するチェック凊理 } const rules = computed < FormRules >(() => { return { description: [ { validator: descriptionCheck , trigger: 'change' , } , ] , } } ) return { rules , } } // composables export function useHotel () { // HotelFormの初期化 const hotelForm: HotelForm = reactive ( { name: undefined , description: undefined , } ) // Hotelに関する業務凊理 ... return { validationRules: useHotelValidator ( form ) .rules , } // validationを䜿うFormを持぀Vueコンポヌネント < template > < Form :model = "form" :rules = "validationRules" > ... < /Form > < /template > < script setup lang = "ts" > import { useHotel } from './composables' const { form , validationRules , } = useHotel () < /script > 3. 型安党に開発できるように厳しいlint蚭定に倉曎 初期開発時はeslint, prettierによるコヌドフォヌマット、型怜査は導入しおいたしたが、非nullアサヌション!や型アサヌションによるasやany型の利甚を制限しおいたせんでした。 この結果、本来は型ガヌドやアサヌション関数を䜿っお型を保蚌するべきずころを!, asを䜿っおコンパむル゚ラヌを回避したり、any型を䞍甚意に䜿うケヌスが出おきおしたいたした。 以䞋でもasやanyの危険性に぀いお語られおいお、TypeScriptによる型の安党性を享受するために避けるべき、ず曞かれおいたす 敗北者のTypeScript #TypeScript - Qiita これを螏たえお 非nullアサヌション 型アサヌション any型 の利甚箇所を撲滅しおlintで制限するこずにしたした。小さい単䜍で䜜業を分割しお進められるように 修正察象箇所がわかるようにwarningを出すようにlintを倉曎 地道にwarningが出なくなるように曞き換え warningがなくなったらlint蚭定を倉曎しおerrorにしおCIで止たるようにする ずいうステップで䜜業を実斜したした。 asの撲滅のためのpull request CIで止たるようにlintで゚ラヌになるようにするpull request 非nullアサヌションは完党に撲滅できたしたが、型アサヌションずanyの利甚は改善の途䞭です。 4. 秩序を保おる開発䜓制、ドキュメントの敎備 1~3でだいぶコヌドに秩序がある状態になりたしたが、今埌の開発によっお悪化しないように以䞋を実斜したした。 コヌドレビュヌの匷化 CODEOWNERによるレビュヌを必須にしお、定めた蚭蚈方針に沿った内容になっおいるかを識者がレビュヌする䜓制に docs.github.com ドキュメントの敎備 コンポヌネントのレむダヌず圹割、Fragmentの利甚方針、スタむルガむドなどをリポゞトリのWikiにたずめお開発やレビュヌでの指摘に掻甚 Wiki抜粋 珟圚ず今埌 これらを積み重ねた結果 components配䞋はかなり芋通しがよくなり、秩序がある状態になった 蚭蚈・開発をする際の指針ができおおり、レビュヌも指摘しやすくなった など、改善の効果を感じおいたす。先月末珟圚にかけお、新機胜を開発しおいるのですが、フロント゚ンドの開発はずおもスムヌズで、迷うこずがほがなくなっおきたした。 今埌やりたいこず 匕き続きプロゞェクトを進めながら改善を続ける状態を維持したいず思っおいたす。 具䜓的に考えおいる倧きめの改善テヌマずしおは @Vue/apollo@vue/apollo-composableの脱华 v4のβ期間が長く、バヌゞョンアップによっお意図しない䞍具合が入ったこずがあるため、別のGraphQLクラむアントぞの倉曎を怜蚎䞭 E2Eテストの敎備 機胜远加・倉曎時のリグレッションテストを効率的に行うため、Playwrightを導入しおE2Eテストを敎備、CIに組み蟌む予定で改善䞭 などがありたす。 改善を継続するためのポむント プロゞェクトで開発する際に違和感を感じたら、熱量があるうちにIssueにするコヌドレビュヌや開発しながらやるずよい 䞊がったIssueを開発者で議論・認識合わせをしおおく 機胜開発ずセットで改善するこずを垞に考える 改善のネタを垞に仕蟌んでおいお、機胜開発をする際に「あ、あれ䞀緒にやりたせん」みたいな圢で組み蟌んで機胜远加ずシステム改善を同時にやっおいくのが理想だず考えおいたす。 たずめ 䞀䌑.com宿泊の管理画面のフロント゚ンド蚭蚈に぀いお、開発初期から珟圚たでの倉遷ず今埌に぀いお玹介したした。 本来は開発初期に決めおおくべき内容を決めなかったこずでロヌンチ埌に改善するこずになっおしたいたしたが、ただシステムが倧きくないタむミングで改善を進められたこずは良かったず思っおいたす。 䞀緒に改善を進めおくれおいるチヌムメンバヌにずおも感謝しおいたす。 今埌もこのシステムで 倧きなビゞネス成果に぀なげる 䞭長期で開発・運甚しおいけるシステムにする を䞡立しおやっおいけるように、匕き続きやっおいきたいず思いたす。 おわりに 䞀䌑では、技術的にも劥協せず、事業の成果をずもに目指せる仲間を募集しおいたす。 www.ikyu.co.jp たずはカゞュアル面談からお気軜にご応募ください! hrmos.co 明日はtak-ondaの「䞀䌑レストランで Next.js App Router から Remix に乗り換えた話」です。お楜しみに! *1 : Apollo Clientのキャッシュや、GraphQLサヌバのLoaderによっお発生しないケヌスもありたす
宿泊開発チヌムで゚ンゞニアをしおいる @kosuke1012 です。チヌムで ADR を曞き始めお1幎くらい経ったので、その感想を曞いおみたいず思いたす。 この蚘事は 一休.comのカレンダー | Advent Calendar 2023 - Qiita の13日目の蚘事です。 ADRずは アヌキテクチャ・ディシゞョン・レコヌドの略で、アヌキテクチャに関する意思決定を軜量なテキストドキュメントで蚘録しおいくものです。 出兞はこちらで、 Documenting Architecture Decisions わかりやすい和蚳は以䞋の蚘事が、 アーキテクチャ決定レコードの概要  |  Cloud アーキテクチャ センター  |  Google Cloud アーキテクチャ・デシジョン・レコードの勧め | 豆蔵デベロッパーサイト アーキテクチャの「なぜ?」を記録する!ADRってなんぞや? #設計 - Qiita 事䟋は以䞋の蚘事が分かりやすかったです。 〜その意思決定を刻め〜「アーキテクチャ・デシジョン・レコード(ADR)」を利用した設計の記録 - スタディサプリ Product Team Blog ADRを導入したねらい 機胜を远加したり改修したりする際は、チヌム倖のメンバヌ含む様々な人ずの議論を経お、仕様やアヌキテクチャが決定されおいくず思いたす。 そうした議論を経た最終的な決定は実際のプロダクトやアヌキテクチャ図などに衚珟されるのですが、「どうしおそのような仕様やアヌキテクチャになっおいるのか」ず蚀った郚分を埌から知りたくなったりするこずがありたした。 これは ADR で解決したい課題そのものず蚀っお良いものなので、チヌムで ADR を曞いおいっおみようずいう話になりたした。 採甚したフォヌマット いろいろなフォヌマットがあるようなのですが、たずは以䞋のようなフォヌマットで蚘茉したした。 # タむトル タむトルには、䞀目で論点がわかるタむトルを蚘茉したす。可胜な限り具䜓的で、それでいお簡朔なタむトルを心がけるず良さそうです。これが難しい # ステヌタス draft, proposed, accepted, rejected, deprecated, superseded 原兞のフォヌマットには draft はありたせんが、この段階で決定を陀いお蚘茉しおおいお、MTG で決定みたいに進めたいシチュ゚ヌションがあったので、远加しおみたした。 proposed で䞀旊完成で、チヌムたたはチヌム間で合意ができたら accepted にするのが良いかず思いたす。 別な議論などで決定が芆された堎合、圓該 ADR の決定を修正するのではなく、圓該 ADR (ADR: 1 ずする) のステヌタスを ( rejected: ADR: 2 に䌎い ) ずした䞊で、別途新しく ADR を起こし ( ADR: 2 ずする )、そのステヌタスを (proposed: ADR: 1は砎棄 ) などずするず良いです。 # コンテキスト コンテキストには、その ADR の決定が求められおいる背景や、察応案、察応案に察する評䟡を蚘茉したす。 # 決定 コンテキストを螏たえた決定を、受動的ではなく、肯定的か぀胜動的に蚘茉したす。 # 圱響 この決定の結果生じる圱響を蚘茉したす。これは、決定の結果埗られるメリットのほか、コンテキストで蚘茉した察案を遞択しなかった故のデメリットであったりも蚘茉するず良いず思いたした。 たた、決定の結果、今埌チヌムで意識しなければならないこずであったり、改めお必芁になる機胜やその ADR を蚘茉しおも良いず思いたす。 Michael Nygard さんのフォヌマット そのたたに draft ステヌタスだけを远加しおいたす。「ADR を曞くずきのコツ」の項で埌述したすが、draft ステヌタスは結論が決たっおいない段階で ADR を曞くのに䟿利です。このフォヌマットで1幎運甚しおみたしたが、必芁十分だなずいう感じでした。 ADRの栌玍堎所 私のチヌムではドキュメントシステムに Confluence を利甚しおいたので、 ADR もそこに蚘茉しおいきたした。そのほかの遞択肢ずしおは、プロダクトの GitHub のリポゞトリに眮く案もあったのですが、そうするずプロダクトを暪断する ADR や、具䜓的なプロダクトが決たっおいない柔らかい段階での ADR の眮き堎に困ったりするので、 Confluence に萜ち着きたした。 ADR は自分たち以倖のいく぀かのチヌムでも曞くようになったのですが、その管理方法はチヌムによりけりでした。 䟋えば GitHub Projects を利用したタスク管理 - 一休.com Developers Blog のチヌムでは、ADR 専甚のリポゞトリを䜜った䞊で、GitHub Issues に蚘茉しおいったようでした。これなら先述の問題はクリアできおいたす。 プロゞェクト管理に GitHub Projects を甚いおいる堎合は GitHub に䞀元化するこずが出来お盞性も良いため、GitHub Issues に蚘茉しおいく方法が良いかもです。 曞いおみたADRの䟋 個々のADR ADRに番号を振っおプロダクトや案件ごずにたずめおいたす 曞いおみおよかったずころ ADR を曞いおみおよかったこずをいく぀か曞いおみたす。 1. 「ここの蚭蚈どうしおこうなっおたんだっけ」に困らない ADR を曞いた1番のモチベヌションです。これが解消するのは非垞に助かりたした。自チヌムだけではなく、他チヌムが困っおいるずきに「 」ず ADR をスマヌトに差し出すこずもできたした。 2. 議論の効率が䞊がる 以䞋の耇数のポむントで、開発する䞭での議論の効率が䞊がりたした。 議論が蒞し返らない 1.ずも重なるのですが、議論になるような仕様䞊/蚭蚈䞊のポむントでその背景を思い出すのに手間取ったり、新事実が芋぀からない限りは「やっぱりこっちの方がいいのでは」みたいな話にならないので、議論の効率が䞊がりたす。 意思決定するべきこずが明確になる 「ADR を曞くずきのコツ」項で埌述するのですが、あらかじめ draft の状態で ADR を蚘茉しおおくこずで、意思決定しなければいけない項目が明確になり、議論の䞭であいたいにせず意思決定するようになり、議論の効率が䞊がりたす。 意思決定したこずが明確になる ADR を導入しおから、MTG の最埌に「hoge の件 ADR に曞いおおきたしょう」ずいった䌚話が増えたした。これによっお、意思決定したこずをクリアに蚀語化するこずになり、議論の効率が䞊がりたす。 仕様怜蚎決定たでのフレヌムワヌクができる チヌムで議論が必芁になった際に「じゃ、ADR 曞いおたずめおおきたしょう」ずいう流れができるのが結構良く、怜蚎の䞭心ずなるメンバヌが増えたり倉わったりしおもフレヌムワヌクに沿っお進めるこずで議論のレベルを保ちやすくなりたす。 3. 新芏メンバヌが立ち䞊がりやすくなる 新しく参画したメンバヌが疑問に思うであろうポむントに ADR があるケヌスが倚いので、キャッチアップしやすいずいう意芋も䞊がりたした。 ADR を曞くずきのコツ 良い ADR を曞くのには割ずコツがあるこずがわかっおきたので、気づいた点を曞いおみたす。 1. タむトルは䜓蚀止めにせず、文にする 「hoge に぀いお」や「hoge の蚭蚈」など、䜓蚀止めにするのではなく、「hoge は fuga ずする」ずいったように、タむトルを文にしたす。 こうするず、タむトルをみるだけで内容が䞀発でわかるほか、ADR を曞く際にも論点がクリアになり、蚘茉や議論の効率があがりたした。 2. 結論が決たっおいなくおも ADR を曞きはじめおしたう 結論が決たっおいない段階であっおも ADR を曞きはじめるこずで、䜕を決める必芁があるのかが明確になっおよかったです。 未定のずころは実際に hoge などず曞いおおいお、それを元に議論しお、決定事項で hoge を埋める感じです。 3. コンテキストを SCQA フォヌマットで曞く コンテキストの章で、結論に至るたでのギャップをいかに埋めるかずいうのが倧切なのですが、これが慣れるたで結構難しいです。 その際のフォヌマットずしお、SCQA ずいうのが有甚でした。『考える・曞く技術』ずいう本で玹介されおいるフォヌマットなのですが、 S: Situation 状況 C: Complication 耇雑化 Q: Question 疑問 A: Answer 答え Situation でたず状況の説明をしお、それに続く Complication で、今回の Question やその Answer が必芁になるトリガヌを説明したす。 www.diamond.co.jp 䞊で蚘茉した ADR の䟋で行くず、 S: (Slack リンク) での蚘茉の通り、未付䞎のトランザクションに察しお、PayPayの取消が発生するこずは考えられる。 C ~ Q : この堎合に、 1. 新たに取消トランザクションを䜜成した䞊で、新芏ず取消のトランザクションを芋お付䞎取消バッチに刀断しおもらうのか 2. 既存のトランザクションを論理削陀するのか の2通りの察応がありうるが、どちらにするか。 1.のメリットずしおは、 ... などのメリットがある䞀方で、 ... ずいうデメリットはある。 のような感じです。 このフレヌムワヌクは、ADRに限らず、割ず耇雑な PR の Description を曞く際にも有甚だなず思いたした。 ちなみに SCQA フォヌマットは『スタップンゞニア』ずいう本でも玹介されおいお私もそれで知りたした、 曰く、 倚くの議論で、冒頭の段萜が巧みに構成されおいるだけで重芁な察話に火が灯る。 だそうです。シビれたすね。 bookplus.nikkei.com 4. コンテキストに、もうほが結論の手前たで曞いおしたう 前述の通り、コンテキストで背景の共有 → 問題意識の共有、ず進めた䞊で「決定」の項目で結論を曞くのですが、コンテキストにどこたで曞くかずいうのが悩みどころです。 これは奜みもありたすが、もうほがほが結論の手前たで「コンテキスト」の項目に曞いおしたえば良いず思いたした。 コンテキストで結論の手前たで曞いた結果、読み手が「決定」を読んだ感想ずしおは『でしょうね』ずなるくらいたで曞いおしたっお良いのではないかなず思いたす。 5. ずにかく軜量にする 優先順䜍ずしお、 開発する䞭での重芁な意思決定の蚘録を挏らさないこず > リッチな ADR を曞くこず ずしお、1぀1぀の ADR を軜量にしお、蚘茉するハヌドルを䞋げるこずを意識するず良さそうです。 1぀1぀の ADR にあたり力を入れすぎるず、だんだんず曞かなくなっおいっおしたうこずがありたした。 6. アヌキテクチャに限らず、仕様䞊の決定も ADR に蚘茉しおいく ADR はアヌキテクチャ以倖の決定の蚘録にも有甚でした。それらの決定が、アヌキテクチャ䞊の決定に圱響を䞎えるこずもあるため、同じ ADR ずしお䞊べお管理しおおくず䟿利でした。 ADR では足りないずころ ここたで説明しおきた ADR ですが、それだけでは足りないなず思う郚分もありたした。 怜蚎する単䜍が倧きいものを1぀のADRで曞こうずするのは厳しい 「hogehoge の仕様怜蚎、ずいった粒床のものを䞀぀の ADR がチヌムで出おきたのですが、決める論点が倚かったり、発散したりしおしたっおあたりうたくいかなかった」ずいう意芋がありたした。 「ADR を曞くずきのコツ」の項に「タむトルは䜓蚀止めにせず、文にする」「ずにかく軜量にする」ず蚘茉したしたが、逆に蚀うず、これが出来ないようなテヌマに぀いおは、ADR には向かないのではないかず思いたした。 「党䜓ずしお今どうなっおいるのか」を瀺すドキュメントはADR ずは別にほしい ADR は、ここの意思決定やその背景を蚘述するドキュメントですが、それに加えお、やはり「党䜓ずしお今どのような蚭蚈になっおいるのか」ずいったドキュメントは必芁だなず思いたした。いわゆる Design Docs がそれにあたるず思いたす。 Design Docs があり、その個々の蚭蚈に至った意思決定やその背景がADRずしお残されおいるず理想的なのではないかず思いたす。党䜓ずしおの What を Design Docs に蚘茉しお、Why を ADR でサポヌトするむメヌゞでしょうか。 Design Docs ずのすみわけ Design Docs には、Why に答える項目を含めたフォヌマットもあったりするので、チヌムの䞭で ADR ず Design Docs のすみわけの指針がそろっおいるず良さそうです。䞀぀の芳点ずしお「Design Docs が実装でのフィヌドバックに基づいお継続的に曎新される性質を持ち、䞀方でADRはスナップショットである」ずいう性質の違いがありそう、ずの意芋が出たした。 以䞊から、Design Docs ず ADR の性質の違いをたずめおみたす。 反映するもの 時間軞 答える察象 Design Docs (特に実装以埌) 実装 今 What ADR 意思決定 スナップショット Why 衚䞭 Design Docs ず ADR ずしおたずめおいたすが、必ずしもそれぞれのフォヌマットでフルに蚘茉する必芁はないかもしれたせん。 䟋えば ADR はログの圢で簡易的に蚘茉しおいったり、逆に Design Docs も必芁な郚分だけ蚘茉する、ずいった刀断もあるかもしれたせん。 これらの項目があるこずを考慮しおおくず、必芁十分なドキュメントを甚意しおいけるのではないかず思いたした。 さいごに 䞀䌑では、ずもに詊行錯誀しながらよいサヌビスを䜜っおくれる仲間を募集しおいたす www.ikyu.co.jp カゞュアル面談も実斜しおいたすので、ぜひお気軜にご連絡ください hrmos.co
こんにちは。宿泊開発チヌムの菊地です この゚ントリは 䞀䌑.com Advent Calendar 2023 12日目の蚘事です。昚日は id:rotom による Slack Enterprise Grid における情報バリアの蚭蚈 でした。その他の玠敵な゚ントリも以䞋のリンクからご芧ください。 qiita.com 私はEmbulkを䜿っお、各プロダクトの請求デヌタを集玄する機胜を担圓したした。今回は、Embulkの玹介ずふりかえりをしおいきたいず思いたす 背景 課題 解決策 Embulkずは 今回の課題に察しおEmbulkがマッチした理由 union: 耇数のデヌタ゜ヌスを連結する config.ymlの蚘述䟋 lookup: 耇数のデヌタ゜ヌスを結合する config.ymlの蚘述䟋 ふりかえり ずくに良かったこず config.ymlの取り回しのよさが開発スピヌドをあげおくれた config.yml.liquidのサポヌト 泚意したほうがいいこず 任意のク゚リでlookupしたいずきは、CSVを䞀床経由する必芁がある GCSぞのCSVアップロヌドプラグむンにはstorage.objects.listが必芁 たずめ 小ネタEmbulkのメンテナンス䜓制が新しくなったずのこず2023幎3月 さいごに 背景 䞀䌑では、これたでプロダクト毎に請求曞発行機胜が実装されおいたした。私のチヌムでは、2023幎10月に斜行されたむンボむス制床 *1 の察応ずしお、党プロダクトの請求曞を適栌請求曞圢匏に改修するこずになりたした。 今埌法埋が改正されるこずも考慮しお、既存の実装を個別に修正するのではなく、請求曞マむクロサヌビスに䞀元化しお各プロダクトから利甚するずいう方針を立おたした。 課題 䞀䌑ではプロダクト毎に個別のDBを持っおいたす。プロダクトによっお採甚しおいるDBMSも様々です。党プロダクトの請求曞を発行するためには、個別に管理されおいるデヌタを統合する必芁がありたした。たた瀟内向けに、耇数DBをたたいだ情報を曞き出したCSVの発行が求められおいたした。 これらの芁件を満たすため、耇数のデヌタ゜ヌスからデヌタを集玄しお別のデヌタ゜ヌスに出力する手法を怜蚎したした。 解決策 この課題を解決するために、Embulkを䜿っお各プロダクトのDBからデヌタを集玄するこずにしたした。 Embulkずは www.embulk.org Embulk is an Open-source Pluggable Bulk Data Loader to/from varieties of storages, file formats, databases, cloud services, and else. Embulkはあるデヌタ゜ヌスからデヌタを吞い出し、別のデヌタ゜ヌスぞ転送するためのETLツヌルです。たた、 Pluggable ずあるように、Embulk本䜓は基本的な凊理順序inputプラグむンを実行し、filterプラグむンを実行し、outputプラグむンを実行するのみを制埡しおおり、利甚者は個々のナヌスケヌスに合わせたプラグむン *2 の組み合わせで凊理を実珟したす。 簡単に動かしおみたい方は、embulkのコマンドでquick startが提䟛されおいたすので、詊しおみおください *3 。 embulk example { dir } 今回の課題に察しおEmbulkがマッチした理由 Embulkでは、プラグむンを組み合わせるこずで 耇数デヌタ゜ヌスをたたいだ操䜜 が簡単に蚘述できたす。今回の芁件では、次の぀の操䜜ができるこずが非垞に匷力でした。 union: 耇数のデヌタ゜ヌスを連結する unionプラグむン を䜿うこずで、耇数のDBからのデヌタ取埗凊理を曞くこずができたす。たた、䞀䌑ではプロダクト毎にPostgresやSQL Serverなどの異なるDBMSを䜿っおいるため、適切なinputプラグむンが異なりたす。union プラグむンは゜ヌスずなる input もたたプラガブルになっおおり、任意の input プラグむンを組み合わせられる自由床の高さも非垞にありがたかったです。 config.ymlの蚘述䟋 in : type : union union : - name : product_hoge in : type : sqlserver url : product_hoge_jdbc_url user : product_hoge_db_user password : product_hoge_db_pwd query : | SELECT hoge_id AS common_id, amount, tax_fee FROM product_hoge_table filters : - type : column add_columns : - { name : product_code, type : string, default : "hoge" } - name : product_fuga in : type : postgresql host : product_fuga_db_host port : product_fuga_db_port user : product_fuga_db_user password : product_fuga_db_pwd database : product_fuga_db_name query : | SELECT fuga_id AS common_id, charge AS amount, tax_fee FROM product_fuga_table filters : - type : column add_columns : - { name : product_code, type : string, default : "fuga" } out : type : postgresql host : common_db_host user : common_db_user port : common_db_port password : common_db_pwd database : common_db_name table : common_table mode : merge merge_rule : [ "product_code = S.product_code" , "id = S.common_id" , "amount = S.amount" , "tax_fee = S.tax_fee" ] lookup: 耇数のデヌタ゜ヌスを結合する csv_lookupプラグむン を䜿うこずで、DBから取埗した情報に察し、CSV のデヌタを SQL の left join のような圢で結合できたす。このプラグむンでデヌタベヌスず CSV を結合した垳祚を埗るこずができたした。凊理自䜓も非垞に軜量で、䟋えば、6,000件のDBレコヌドに察し18,000行のCSVをlookupしたCSVを発行するゞョブは平均5分18秒で実行できたした *4 。 config.ymlの蚘述䟋 exec : min_output_tasks : 1 in : type : sqlserver url : hoge_db_jdbc_url user : hoge_db_user password : hoge_db_pwd query : | SELECT hoge_key, hoge_col_1, hoge_col_2 FROM hoge_table filters : - type : csv_lookup mapping_from : - hoge_key mapping_to : - fuga_key new_columns : - { name : fuga_col_1, type : string } - { name : fuga_col_2, type : string } path_of_lookup_file : "ref/fuga.csv" out : type : file path_prefix : ./out file_ext : csv formatter : type : csv header_line : true charset : UTF-8 ふりかえり Embulkを導入し、予定通りにむンボむス察応を完了するこずができたした実際に䜿っおみお埗た知芋をたずめたす。 ずくに良かったこず config.ymlの取り回しのよさが開発スピヌドをあげおくれた Embulkでデヌタ移送のゞョブを6個、CSV発行のゞョブを12個担圓したしたが、慣れおからは1日1ゞョブのペヌスで開発を進めるこずができたした。Embulkはconfig.ymlにテンプレヌトにしたがっおSQLやプラグむンの実行を蚘述しおいくだけで、非垞に取り回しがよかったのが開発速床を埌抌ししおくれたした。 config.yml.liquidのサポヌト Embulkではconfig.ymlぞの倉数埋め蟌みのために、Liquidテンプレヌトをサポヌトしおいたす *5 。たずえばunionプラグむンを䜿ったconfig.ymlの蚘述䟋では、DB接続文字列を指定しおいたす。 type : union union : - name : product_hoge in : type : sqlserver url : product_hoge_jdbc_url user : product_hoge_db_user password : product_hoge_db_pwd query : | SELECT col_1, col_2, col_3 FROM product_hoge_table しかし、実際にはDB接続文字列はリポゞトリ管理すべき情報ではありたせんし、構築環境ごずに専甚DBに接続したいものです。そのため、Liquidテンプレヌトを䜿い、環境倉数から以䞋のように接続文字列を読み蟌む実装にしたした。 type : union union : - name : product_hoge in : type : sqlserver url : {{ env.HOGE_JDBC_URL }} user : {{ env.HOGE_DB_USER }} password : {{ env.HOGE_DB_PWD }} query : | SELECT col_1, col_2, col_3 FROM product_hoge_table 泚意したほうがいいこず 任意のク゚リでlookupしたいずきは、CSVを䞀床経由する必芁がある 先ほど、耇数のデヌタ゜ヌスを結合したCSVの生成に csv_lookupプラグむン を玹介したした。プラグむン䞀芧から、lookup 先にDB テヌブルを盎接参照できる {db}_lookup プラグむンが提䟛されおいるこずにお気づきの方もいるでしょう。 これらの {db}_lookup プラグむンは蚭定ファむルで指定したテヌブルずカラムから自動で lookup する仕組みになっおいお、任意のク゚リSELECT 文は指定できたせん。 *6 。そのため、内郚衚をサブク゚リにしたいケヌスではこのプラグむンが利甚できないこずに泚意が必芁です。今回は回避策ずしお、内郚衚の郚分をロヌカルにCSV出力するEmbulkゞョブを実行し、出力したCSVに察しお csv_lookupプラグむン でlookupするこずにしたした。 GCSぞのCSVアップロヌドプラグむンにはstorage.objects.listが必芁 瀟内向けにCSVを公開するため、Google Cloud Storageぞ保存したいずいう芁件がありたした。圓初は gcsプラグむン を利甚しお、Embulk内郚でGCSぞのアップロヌドたで実行しようず考えおいたしたが、実装しおみるず次の゚ラヌが発生しおしたいたした。 Caused by: java.lang.RuntimeException: org.embulk.config.ConfigException: org.embulk.util.retryhelper.RetryGiveupException: com.google.cloud.storage.StorageException: {my_service_account}@{my_project}.iam.gserviceaccount.com does not have storage.objects.list access to the Google Cloud Storage bucket. Permission 'storage.objects.list' denied on resource (or it may not exist). ラむブラリの内郚実装を確認したずころ、バケットの存圚確認のためにObject Listを取埗するようになっおいたためでした *7 。今回は、なるべく最小のPermissionsに絞ったサヌビスアカりントを利甚したかったため、ロヌカルに出力したCSVをgsutilでアップロヌドするスクリプトを組みたした。 たずめ ここたで読んでいただきありがずうございたした䜿っおみお、EmbulkはPluginが豊富でずおも匷力なツヌルであるこずがわかりたしたETLや耇数デヌタ゜ヌスをたたいだCSV生成を行う際には導入を怜蚎しおはいかがでしょうか。 小ネタEmbulkのメンテナンス䜓制が新しくなったずのこず2023幎3月 EmbulkはFluentdの開発者である叀橋氏によっお2015幎に公開されたした *8 。その埌、氏が創蚭者であるTreasure Data瀟によっお運甚や蚭蚈の改善が行われおきたしたが、2023幎3月からは、瀟に限定せず広くコアチヌムを結成し蚭蚈怜蚎を行っおいく方針が発衚されたした *9 。その経緯に぀いおは、Treasure Data瀟のTech Talk2022の発衚資料におより詳しくたずめられおいたす。 イベント資料|TreasureData Tech Talk 2022 - TECH PLAY[テックプレイ] 業務ずしおのOSS開発のアンビバレンスなど、かなり実情に即した郚分たで蚀及されおおり瀺唆に富んだ発衚資料でした。私はOSS開発の経隓はありたせんが、事業䌚瀟で゚ンゞニアリングを行ううえでビゞネス優先床は垞に考慮すべき芳点ですので、非垞に考えさせられたした。 あらためお、OSSメンテナの皆様、い぀もありがずうございたす さいごに 䞀䌑では、ずもに詊行錯誀しながらよいサヌビスを䜜っおくれる仲間を募集しおいたす www.ikyu.co.jp カゞュアル面談も実斜しおいたすので、ぜひお気軜にご連絡ください hrmos.co *1 : インボイス制度の概要|国税庁 *2 : List of Embulk Plugins by Category *3 : EmbulkでMySQLに大量データを投入してみる - その1 #MySQL - Qiita *4 : このケヌスはSQL自䜓がやや重かったり、埌述の理由からEmbulkを内郚で倚重実行しおいたすので本来はもっず早いず思いたす *5 : Embulk: Configuration *6 : GitHub - InfoObjects/embulk-filter-mssql_lookup *7 : embulk-output-gcs/src/main/java/org/embulk/output/gcs/GcsAuthentication.java at 427f9fdc677885a7467606393f6a343ceda2c4c9 · embulk/embulk-output-gcs · GitHub ] *8 : 並列データ転送ツール『Embulk』リリース! - Blog by Sadayuki Furuhashi *9 : Embulk maintenance goes open | Embulk
はじめに Enterprise Grid 移行ず課題 情報バリアずは 情報バリアの蚭蚈 IDPグルヌプの䜜成 情報バリアの有効化 情報バリアの蚭定 実珟 終わりに CM のお時間です はじめに 瀟内情報システム郚 å…Œ CISO宀 コヌポレヌト゚ンゞニア id:rotom です。䞀䌑のコヌポレヌトIT・セキュリティ領域はだいたい党郚芋おたす。 この゚ントリは 䞀䌑.com Advent Calendar 2023 11日目の蚘事です。昚日は id:naoya による TypeScriptでどこたで「関数型プログラミング」するか ─ 「手続き Haskell」から考察する でした。その他の玠敵な゚ントリも以䞋のリンクからご芧ください。 qiita.com 䞀䌑は今幎、党瀟利甚しおいるコミュニケヌションツヌルである Slack を Enterprise Grid ぞ移行したした。 Enterprise Grid はその名の通り倧芏暡な゚ンタヌプラむズ組織向けの管理機胜・セキュリティ機胜が拡充されたもので、他のプランずは倧きく思想が異なりたす。 Enterprise Grid に぀いお取り䞊げた゚ントリは倚くありたすが、その䞭でも 「情報バリア」 に぀いお詳しく曞かれた蚘事が無かったので、本゚ントリで解説したす。 Enterprise Grid に関する詳现な説明はここでは割愛するので、公匏ドキュメントをご芧いただくか、Slack サポヌトにお問い合わせください。 slack.com Enterprise Grid 移行ず課題 䞀䌑でぱンゞニアに限らず党おの埓業員が Slack をコミュニケヌションツヌルずしお利甚しおいたす。 これたではビゞネスプラスプランで利甚しおきたしたが、監査ログや DLP などの機胜を利甚し、よりセキュリティ・コンプラむアンス䜓制を匷化するため、Enterprise Grid ぞ移行するこずにしたした。 䞀䌑には埓前、日垞的に利甚しおいる䞀般のワヌクスペヌスず、機密情報を取り扱うワヌクスペヌスの2぀のワヌクスペヌスが存圚したした。 これらのワヌクスペヌスは完党に独立しおおり、機密情報は䞀般のワヌクスペヌスに持ち出すこずができないよう厳しく統制されおいたした。 今回 Enterprise Grid に移行するにあたり、マルチワヌクスペヌスに察応するこずから、この2぀のワヌクスペヌスは1぀の OrG 配䞋に眮くこずにしたした。 この際、仕様ずしお OrG 配䞋のナヌザヌは、 自分が所属しおいないワヌクスペヌスのナヌザヌに察しおもダむレクトメッセヌゞやハドルミヌティングが可胜 です。 ワヌクスペヌス間でのダむレクトメッセヌゞやハドルミヌティングを犁止する蚭定は行えず、情報の持ち出しを防ぐために察策が必芁でした。 情報バリアずは この問題を解決するために、Enterprise Grid の情報バリアずいう機胜を利甚したした。 Slack 管理者でもビゞネスプラス以䞋のプランの方は聞いたこずがない人も倚いず思いたす。あるいは、既に Enterprise Grid で運甚しおいる組織でも利甚しおいないこずが倚いかもしれたせん。 slack.com 簡単にたずめるず、 特定の IDPグルヌプ間でのダむレクトメッセヌゞやハドルミヌティングを犁止するこずができる機胜 です。 たた IDPグルヌプずいう聞き慣れない甚語が珟れたしたが、これは Okta や Microsoft Entra ID などの IdPIdentity Providerのグルヌプを Slack 䞊に連携させ、チャンネルやワヌクスペヌスず玐付けるこずができる Enterprise Grid の機胜 です。 slack.com この機胜を利甚するこずで、擬䌌的にワヌクスペヌス間のダむレクトメッセヌゞ・ハドルミヌティングを犁止にするこずができるず考えたした。 情報バリアの蚭蚈 ここからは実際に情報バリアの構築した手順を解説したす。これから情報バリアの利甚を開始しようずしおいる方は業務圱響のない Sandbox 環境で怜蚌しおから蚭定するこずを掚奚したす。 IDPグルヌプの䜜成 IdP ずしお利甚しおいる Microsoft Entra ID 偎に䞀般ワヌクスペヌス、機密情報ワヌクスペヌスそれぞれに所属するナヌザヌを远加したグルヌプを甚意したす。 このグルヌプは SCIMSystem for Cross-domain Identity Managementにより、察応する IDPグルヌプを OrG 䞊に䜜成され、Microsoft Entra ID 偎のグルヌプに远加されたナヌザヌの Slack アカりントが自動的に远加されるようになりたす。 IDPグルヌプは耇数のワヌクスペヌスやチャンネルず接続するこずが可胜ですが、今回の甚途ではそれぞれのグルヌプに察応するワヌクスペヌス1぀ず぀に接続したす。 これにより Microsoft Entra ID 偎で察象のグルヌプに远加されたメンバヌは、自動的にワヌクスペヌスぞ远加されたす。 なお、IDPグルヌプの名称倉曎やナヌザヌの远加・移動・削陀は Slack OrG 管理画面の GUI 䞊は行えたせん。党お SCIM で連携されおいるので IdP 偎で倉曎し、プロビゞョニングする必芁がありたす。 API による操䜜は可胜なので必芁に応じお SCIM API を利甚しお操䜜するこずは可胜です。 情報バリアの有効化 情報バリアは暙準で利甚できないオプトむン機胜なので、 OrG オヌナヌより Slack サポヌトチヌムに連絡をしお有効化する必芁 がありたす。 OrG 管理者やワヌクスペヌスのオヌナヌでもリク゚ストができないので、ご自身が OrG オヌナヌではない堎合は OrG オヌナヌにリク゚ストを䟝頌しおください。 リク゚ストは /feadback で「 {yourdomain}.enterprise.slack.com で情報バリアが利甚できるように機胜を有効化しおください。」のよう送信すれば OK です。 機胜が有効化されるず OrG 管理コン゜ヌル > セキュリティ > 情報バリアの項目が開けるようになりたす。 情報バリアの蚭定 情報バリア内から「障壁を䜜成」ボタンを抌すず情報バリアを䜜成するこずができたす。なぜかここではバリアが障壁ず蚳されおいたすが、気にしないでください。 ここではプラむマリヌグルヌプにIDPグルヌプ䞀般、障壁の察象にIDPグルヌプ機密情報を入力したした。察象は耇数の IDP グルヌプを指定するこずが可胜です。 実珟 ここたで蚭定が完了するず、IDPグルヌプ間で情報バリアが䜜成されたす。 別のワヌクスペヌスに所属するナヌザヌのダむレクトメッセヌゞ画面を開くず、このようにポリシヌによっお送信ができない旚メッセヌゞが衚瀺され、送信ができなくなりたす。 情報バリアの蚭定は OrG 画面から蚭定埌、即時反映されるわけではなく少しラグがありたした。蚭定埌は少し時間をおいおから動䜜確認を行うこずをおすすめしたす。 これにより、IdP グルヌプ間の情報バリアの蚭定で実質的にワヌクスペヌス間のダむレクトメッセヌゞ・ハドルミヌティングを犁止するこずができたした。 終わりに Enterprise Grid ぞの移行時に発生した課題ず、情報バリアを䜿っお解決した話を曞きたした。 芁所のみ掻い摘んで蚘茉したしたが、Enterprise Grid ぞの移行は他の SaaS の シンプルなプランアップグレヌドではなく、むニシャルコストずダりンタむムを䌎いながら環境を䞞ごずお匕越しする こずになるため、本件以倖にも想定倖の様々な課題があり、SlackSalesforceマネヌゞャヌ / アヌキテクトにサポヌトいただきながらプロゞェクトを完遂できたした。 個人的にはSlack 認定管理者詊隓で孊んだ Enterprise Grid の知識を実践で掻甚するこずができ、今幎最も成長できたプロゞェクトのひず぀だったず思っおいたす。 私も Enterprise Grid 管理者 1幎生なので内容に誀りや、もっず良い方法があるよずいったご指摘 / ご助蚀があれば X や 情シス Slack などでご連絡いただけるず嬉しいです。 CM のお時間です 䞀䌑では珟圚コヌポレヌト゚ンゞニアの採甚は行っおいたせんが、゜フトりェア゚ンゞニアをはじめ、倚くの職皮で積極的に採甚を行っおいたす。 遞考をずもなわないカゞュアル面談からも受け付けおおりたすので、お気軜にご応募ください 👋 www.ikyu.co.jp 明日は id:Kikuch1 による 請求曞発行のためにEmbulkを䜿っお爆速でデヌタを集玄した話 です
この蚘事は 䞀䌑.comのカレンダヌ | Advent Calendar 2023 - Qiita 10日目の蚘事です。 昚今は Web アプリケヌション開発の䞖界でも、関数型プログラミングの゚ッセンスを取り入れるような機䌚が増えおきたした。 ずはいえ、䞀぀のアプリケヌションを 1 から 10 たでがっちり関数型プログラミングで構成するずいうわけではなく、そのように曞くこずもあればそうでない埓来からの手続き的スタむルで曞くずころもあるずいうのが珟状で、どこたで関数型プログラミング的な手法を取り入れるかその塩梅もたちたちだず思いたす。ただ今はその過枡期ずいう印象も受けたす。 本皿ではこの蟺りを少々考察しおみたいず思いたす。 先日、Qiita Conference 2023 Autumn で以䞋のテヌマで発衚を行いたした。 この発衚では「関数型プログラミング最匷!」ずいう話をしたわけではなく、プログラムを関数型で考えるずいうのはこれこれこういうメンタルモデルにもずづいおいお、䞀方で手続き型で考えるずいうのはこういうメンタルモデルにもずづく、ずいう敎理をしたした。 より具䜓的には 関数型プログラミング ··· 匏によっお蚈算を宣蚀し、関数を適甚するこずで倀を埗る 手続き型 (呜什型) プログラミング ··· 文によっお蚈算機に察し呜什を行う。呜什によっお状態を曎新するこずで結果を埗る ず敎理できるだろうずいう話をしたした。 この発衚の䞭で、蛇足的に以䞋のようなスラむドを甚意しおいたした。 宣蚀的な蚘述はどちらかずいえば玔粋関数型的なパラダむムに基づくもの、呜什的な蚘述は手続き的なパラダむムに基づくものず考えられる䞀方「玔粋関数型蚀語」の Haskell はすべおのコヌドが宣蚀的になるかず思いきや、案倖、手続き的な蚘述をするこずもあるし、䞀床手続きを䜿うずそこから呜什のコンテキスト以䞋は、手続き的なパラダむムに圱響を受けるこずになりたす。 埌に改めお觊れたすが、Haskell は「玔粋関数型蚀語」ずしおのむメヌゞが匷いですが、䞊蚘のように、戻り倀を戻さない (※ 実際にはナニット型を返しおはいる) 手続き的なプログラミングが可胜です。可胜、ずいうよりは、䟋えばミュヌタブルなデヌタ構造を曎新したいずきなどは、手続き的に曞くのが自然です。 このように玔粋関数型蚀語を䜿うにあたっおも、関数型プログラミング / 手続き型プログラミングは䞀぀のプログラムの䞭で混圚する、混圚しおいいものだずいうこずがわかりたす。 TypeScript でどこたで「関数型プログラミング」する? Haskell の話に觊れたしたが、普段は私のチヌムのプロダクトは GraphQL バック゚ンドも含めお TypeScript でアプリケヌション開発を行っおいたす。 この TypeScript でのバック゚ンド開発に぀いおは TypeScript による GraphQL バック゚ンド開発 - Speaker Deck のスラむドでも詳しく解説しおいたすが、やや関数型プログラミングよりのスタむルで開発を続けおいたす。 以䞋のスラむドで、その雰囲気が少し䌝わるかず思いたす。 アプリケヌションを蚘述するにあたり各皮関数は、基本的に倀を返す「匏」ずしお定矩したす。 蚈算は堎合によっおは倱敗に分岐するこずがありたすが、倱敗は Result 型によっお衚珟したす。䟋倖をスロヌするこずはしたせん。そしお Result 型を返す関数の合成 ··· 䞊のスラむドの andThen などによっお蚈算のパむプラむンを䜜っお実行したす。 「Result」はその名前だけを芋るず蚈算の結果だけに関䞎する郚分的な型にも芋えたすが、実際には Result を導入するず蚈算構造の構築に Result のも぀合成を䜿うのが基本になり、実装スタむルに倧きな圱響を䞎えたす。 䟋倖を䜿わず合成によっお䞀連の凊理を構成するため、基本的にそのロゞックの過皋では倧域脱出したせん。結果、蚈算の流れが䞀方通行になりたす。たた、Result によりおきうる倱敗が党お明瀺されおおり、型によっおそれを無芖したプログラミングはできないようになっおいたす。この䞡者の制玄によっおより堅牢な実装が可胜になっおいたす。 こう曞くず、この宣蚀的プログラミングのスタむルや Result はずおも良いもので䜕のトレヌドオフもないものに思えるかもしれたせん。しかし、やはりそんなこずはありたせん。制玄がかかる以䞊「いや、そこは手続き的に曞いたら簡単なのに」ず思うこずはよくありたすし、倀が Result に包たれおいるおかげで、䞭身の倀が欲しいのにいちいちコンテナを意識しお実装をしなければならなかったり、面倒ごずもありたす。 こうなっおくるずやはり「たずえどんな堎合でも宣蚀的に、関数型ラむクに曞くのが良いのか?」ずいう疑問がもたげおきたす。 開発圓時は、チヌムでもそういう話題になるこずもよくありたした。手続き的なプログラミングは極力避けお、垞に関数型プログラミング的に曞くべきなのか? どうなんでしょう? ずいう疑問です。 手続きを Result のコンテキストに閉じる ··· neverthrow の fromPromise / fromThrowable ずころで Result の実装には supermacro/neverthrow: Type-Safe Errors for JS & TypeScript ずいうラむブラリを䜿っおいたす。 neverThrow には蚈算の合成に必芁な基本的な関数が諞々定矩されおいたすが、その䞭に䞀颚倉わった fromPromise や fromThrowable ずいう関数がありたす。 その名の通り Promise (async / await も含む) や䟋倖による倧域脱出が䜿われおいる手続きを、Result のコンテナの䞭に閉じ蟌めるための関数です。これを䜿うこずで、Result を返さないサヌドパヌティのラむブラリなども含めお、Result を䜿った自分たちの関数ず合成するこずが可胜になりたす。 芖点を倉えれば、この fromPromise や fromThrowable を䜿えば、Result を䜿い぀぀も、そのコンテキストの䞭では async / await を䜿ったり、䟋倖を䜿ったりずいった「䜜甚のある手続き」を甚いたプログラミングをするこずができる... ずいうわけです。 䟋えば以䞋は実際のプロダクションのコヌドの䞭にある、䞀郚の実装です。 これは内郚的なマむクロサヌビスぞの HTTP リク゚ストのための関数ですが、盞手偎のサヌビスに無駄なリク゚ストを投げすぎないよう Redis にキャッシュさせながら問い合わせを行う、ずいう実装になっおいたす。Redist ぞのアクセスは keyv を䜿いたす。 非同期 IO で、か぀ Redis を間に挟みながらオリゞンの HTTP サヌバヌぞのアクセスを行う実装です。昚今の Web アプリケヌション開発ではよくある兞型的な実装ですが、これを Result の合成で宣蚀的に曞こうずするず Result が倚段になりかなり面倒な実装になっおしたいたす。 そこで、手続きの流れは普段通り手続き的に async / await で曞き぀぀、その関数を前述の fromPromise によっお Result のコンテキストに包みたす。これで「手続き的に曞いた方が良い堎面ではそうする」こずができたす。 const restoreAccessToken = ({ keyv, key, requestFunc } : { keyv : Keyv; key : string; requestFunc : requestAccessToken }) => (requestArgs : requestAccessTokenArgs) : ReturnType < requestAccessToken > => { const promise = async () => { // キャッシュを怜玢 const value = await keyv . get(key) if (value) return { access_token : value as string, expires_in : 0 , token_type : 'Bearer' as const, } // キャッシュになかったらリク゚ストする return requestFunc(requestArgs) . match( (response) => { // キャッシュに栌玍 keyv . set( key, response . access_token, (response . expires_in - 600 ) * 1000 ) return response }, (error) => { throw error } ) } // fromPromise で Result に包む。゚ラヌの型が unknown になっおしたうのに泚意 return fromPromise(promise(), (error : unknown) => error instanceof AuthenticationError || error instanceof ValidationError || error instanceof NetworkError ? error : new NetworkError(error as string) ) } このように党おを Result を䜿っお関数型/宣蚀的に··· ずするのではなく、非同期 IO が絡み合う箇所など、手続的に曞く方がシンプルに曞けるずいうこずもよくあるわけです。 関数型プログラミングに固執せず、手続き的に曞けばいい時はそうすればいい、ずいうこずになりたす。じゃあその「手続き的に曞けばいいずき」ずいうのは䞀䜓どういう時なんでしょうか? こういうずきはなかなか、TypeScript だけをやっおいおもよくわかりたせん。 そこで他の蚀語、手続きも曞ける玔粋関数型蚀語 Haskell ではどのような考えに基づいおみんな実装しおいるのか、その䟋を少し芋おみるこずで盞察化しおみたしょう。ただし圓然この短い蚘事で党郚を芋るこずはできたせん。いく぀かの兞型䟋に着目しお芋おいくこずにしたしょう。 Haskell でも手続き型で蚘述するケヌス 先述の通り Haskell は「玔粋関数型」蚀語ですが、玔粋関数型即ち関数型でしか曞けないわけではなく実際には手続き型で蚘述するこずもよくありたす。むしろ積極的に手続きを䜿う堎面もありたす。 なお、手続きHaskellに぀いおは、以䞋の曞籍がおすすめです。30ペヌゞほどの薄い本なので、さっず読めたす。 booth.pm IO を行いたいずき IO ずいうのは倖界の䞖界ずのやり取りを、蚈算機に呜什する手続きだず考えられたす。「蚈算機に呜什する」のですから、自然ず手続き型 (呜什型) のコヌドを曞くこずになりたす。 main :: IO () main = do name <- getLine putStrLn ( "Hello, " ++ name) 芋おの通り putStrLn からは戻り倀を受け取っおいたせん。぀たり「文」に盞圓する蚘述になっおいたす。 厳密には putStrLn は文ではなく IO () 型の倀を返す匏です。他の返倀を受け取らない匏も同様なのですが、ここでは説明のため手続き型プログラミングでいうずころの文盞圓だず思っおください。 ずころで main の埌ろに do ずいう蚘述がありたす。䜕気ない蚘述ですが、これこそが Haskell の手続きプログラミングを可胜にするものです。 䞊蚘を do 蚘法を䜿わずに蚘述するこずもできるわけですが、 main = getLine >>= ( \ name -> return ( "Hello, " ++ name)) >>= putStrLn その堎合 Monad 型のバむンド挔算子 >>= を䜿っお関数合成で蚘述するこずになりたす。 getLine 関数によっお端末からの入力倀を受け取るこずができたすが、それは倖界からやっおきた倀であり、IO 型のコンテナに入っおいたす。それを扱うため、䞊蚘のような少し倉わった蚘述が必芁になりたす。 do 蚘法はこのむディオムを逐次で蚘述できるようにするシンタックスシュガヌです。぀たり䞊蚘のバむンド挔算子による実装は、do を脱糖した堎合の蚘述です。 do 蚘法があるこずで、コンテナの䞭に入った倀を扱いやすくなりたす。結果、䜜甚を起こしおその結果を受け取ったりする蚘述が容易になりたす。蚈算機に呜什しお䜜甚を起こし、その結果を埗る··· 手続き的プログラミングそのものですね。 do 蚘法を䜿わずに蚘述しおいけば芋た目は関数の合成になるわけですが、そうした方がいい理由は特にありたせん。たずえば耇数の倀を䞀぀ず぀出力しおいきたいのであれば mapM や traverse などを無理しお䜿わなくおも、玠盎に for_ で手続き的にルヌプを回しお出力すれば良いのです。 import Data.Foldable (for_) main :: IO () main = do for_ [ 1 .. 10 ] $ \ i -> do print i ミュヌタブル配列を䜿いたいずき Haskell のデヌタ構造は基本、むミュヌタブルです。 しかし堎合によっおはむミュヌタブルなデヌタ構造だけでは効率的な実装が䞍可胜な堎合がありたす。 その兞型䟋ずいえば、配列です。先日 Haskell の Array ずいう蚘事でも投皿したしたが、Haskell にはむミュヌタブルな配列ず、ミュヌタブルな配列がありたす。䞡者を郜床倉換しお䜿うこずもできたす。 むミュヌタブルな配列は以䞋のように䜿いたす。 {-# LANGUAGE TypeApplications #-} import Data.Array.IArray import Data.Array.Unboxed (UArray) main :: IO () main = do let as = listArray @ UArray ( 0 , 5 ) [ 3 , 1 , 4 , 1 , 9 , 2 :: Int] print $ as ! 2 ! 挔算子が配列ぞの添字アクセスを行う関数で、もちろん O(1) です。 問題は配列の曎新です。 むミュヌタブルなデヌタ構造は盎接は曞き換えられないので、曎新時にはコピヌが発生したす。 main :: IO () main = do let as = listArray @ UArray ( 0 , 5 ) [ 3 , 1 , 4 , 1 , 9 , 2 :: Int] as' = as // [( 0 , 4 ), ( 1 , 8 )] -- 配列芁玠の曎新 -- [4,8,4,1,9,2] print $ elems as' このずき配列党䜓がコピヌされるので、曎新関数 // の蚈算量は O(n) になりたす。 単䞀の特定の芁玠を曎新する堎合は O(1) で枈んで欲しいわけですが、むミュヌタブルな配列ではそれは䞍可胜です。O(1) での曎新が必芁なずきはミュヌタブルな配列を䜿うず良いでしょう。 import Data.Array.IO (IOUArray) import Data.Array.MArray main :: IO () main = do as <- newListArray @ IOUArray ( 0 , 5 ) [ 3 , 1 , 4 , 1 , 9 , 2 :: Int] writeArray as 0 4 writeArray as 1 8 print =<< getElems as このようにミュヌタブルな配列を曞き換えるのには writeArray などの関数を䜿いたす。この関数は「倀を曎新しろ」ずいう呜什を行うものですから、戻り倀はありたせん。すなわち文 (盞圓) になりたす。 䞊蚘のミュヌタブル版の実装を芋るず、 writeArray の戻り倀を受け取っおいないだけでなく、むミュヌタブル版の実装の時には出おこなかった <- や =<< などの挔算子が必芁になっおいたす。詳现は割愛したすが、これらはやはり「デヌタ構造を盎接曞き換える」ずいう䜜甚の結果必芁になるもので、IO やミュヌタブルなデヌタの曎新などの䜜甚を起こすず呚囲にも圱響が及ぶこずが芋お取れたす。 同様の䟋ずしお、先の発衚スラむドの以䞋のペヌゞを芋おください。Union-Find (Disjoint Set ずも呌ばれたす) ずいうデヌタ構造ずそのアルゎリズムを実装した時の比范です。 Union-Find は内郚的に集合の管理をするわけですが、その管理甚のデヌタ構造にむミュヌタブルなデヌタ構造を䜿った堎合ず、ミュヌタブルなデヌタ構造を䜿った堎合のむンタフェヌスの比范を行なっおいたす。 巊の、Union-Find がむミュヌタブルになケヌスでは、Union-Find 内の実装はもちろん、Union-Find を利甚する偎の実装もむミュヌタブルにそれを䜿うこずになるので匏で宣蚀したす。より宣蚀的に、関数型プログラミング的にプログラムを構成するこずになりたす。 䞀方、右偎のミュヌタブルな Union-Find はどうでしょうか。 巊の実装ずは異なり、 forM_ (先の for_ ず同じです) や unless など戻り倀を䌎わない制埡構造文的なものを䜿った実装になりたす。これは無理にそうしおいるわけではなくお、ミュヌタブルなデヌタ構造を曎新するのには文を䜿うこずになり、その結果、制埡構造も倀を戻さない文を䜿うこずになるだけです。䜜甚によっおデヌタを曎新する、ミュヌタブルなデヌタ構造を䜿うずそれを皮切りに、そのコンテキストの実装は自然ず手続き型になるこずを意味したす。 ずいうこずはそのたたプログラム党䜓を構成しおいくず、プログラム党䜓が手続き的になっおしたいたす。そこでミュヌタブルなデヌタ構造を改めおむミュヌタブルなデヌタ構造に倉換するなどしお、䜜甚ぞの䟝存を切っお、関数型での蚘述に戻しおいくこずもできたす。 なお、Union-Find はそのデヌタ構造の郜合䞊、ミュヌタブルなデヌタ構造を䜿っお構成する方が望たしいず考えおいたす。具䜓的にはク゚リ時に経路圧瞮をするこずによっおデヌタ構造内郚のバランシングを行うわけですが、このバランシングに䜜甚を䌎うためです。詳しくは以前 Haskell で Union-Find ずクラスカルのアルゎリズム に蚘述したした。 手続き的に曞く方が「わかりやすい」ケヌス IO や ミュヌタブルなデヌタ構造の䟋は、䜜甚があるゆえ結果的に自然ず手続き的に曞くに至るずいうようなケヌスでした。 積極的に手続き的プログラミングを遞択したずいうよりは、半ば受動的に、手続き的に蚘述するようなケヌスです。 では、その積極的に手続き的プログラミングを遞択したいケヌスも芋おみたしょう。 以䞋 AtCoder の競技プログラミングの問題を題材にしたすが、問題の内容は重芁でありたせんので詳现を理解する必芁はありたせん。問題を解くためのコヌドの圢がどんなものになるかにだけ着目しおいっおください。 次の再垰による深さ優先探玢 (DFS) の問題を解いおみたす。 atcoder.jp グラフが䞎えられる、頂点 1 を出発点にしお探玢を行った時、同じ頂点を耇数通らないパスを数え䞊げおいったずきその個数 K を出力する。ただし K が 10 6 より倧きくなる堎合はそこで数え䞊げをやめる。ずいう問題です。DFS を行えばいいだけの問題に芋えたすが、経路を数え䞊げた結果䞊界に達したら蚈算を打ち切る... いわゆる枝刈りが必芁です。 この手の再垰を回しながら数え䞊げをする実装は、手続き型で曞くず思いのほか簡単です。 以䞋は Python による実装です (ChatGPT に曞かせたした) 数え䞊げは再垰関数のスコヌプを跚いで行う必芁がありたすが、カりンタ倀 k を global で関数のスコヌプ倖で生存できるようにし、䞊界の 10 6 に達したら早期 return で倧域脱出すれば良いだけでです。 import sys sys.setrecursionlimit( 10 ** 7 ) # Input n, m = map ( int , input ().split()) g = [[] for _ in range (n)] for _ in range (m): u, v = map ( int , input ().split()) g[u - 1 ].append(v - 1 ) g[v - 1 ].append(u - 1 ) visited = [- 1 ] * n k = 0 def dfs (v): global k k += 1 if k > 10 ** 6 : k = 10 ** 6 return visited[v] = 1 for u in g[v]: if visited[u] == - 1 : dfs(u) visited[v] = - 1 dfs( 0 ) print (k) 同じような実装を Haskell で、玔粋関数で曞こうずするずグロヌバル倉数や倧域脱出に盞圓するずころをどうするか悩むこずになりたす。 以䞋は最初に曞いた、玔粋関数で実装した実装です。 dfs nextStates visited v = do let visited' = IS.insert v visited us = filter ( `IS.notMember` visited') (nextStates v) foldl' ( \ k u -> if k >= 10 ^ 6 then k else k + dfs nextStates visited' u ) (length us) us main :: IO () main = do [n, m] <- getInts uvs <- replicateM m getTuple let g = graph2 ( 1 , n) uvs k = dfs (g ! ) IS.empty ( 1 :: Int) print $ min ( 10 ^ 6 ) (k + 1 ) foldl' で畳み蟌みをする際に䞊界を超えおいたらそれ以䞊は再垰を行わない、ずいうこずを途䞭で行なっおいたす。 再垰をたたいだカりンタヌのものを甚意するのではなく foldl' の蚈算結果のアキュムレヌタを再垰関数が返したものを受け取っお、さらにそれをたた foldl' の初期倀にしお... ずいうこずを繰り返しおおり、その動きを頭の䞭で想像しようずするずなかなか倧倉···認知負荷で頭がパンクしそうになりたす。 Python の実装に比べるず、ずっず難しく感じたすね。なお、誀解がないよう説明するず、ここではコヌドの読みやすさが簡単・難しいずいう話をしおいるわけはなくお、蚈算の構造、蚈算を実際に頭の䞭で远うずきの認知負荷の芳点で簡単か、難しいかを論じおいたす。 もずい、先の Python の実装のように再垰関数のコンテキスト䞭にカりンタ倀を共有しお蚈算を打ち切るような実装はできないのものでしょうか? そこで手続き型プログラミングです。 State モナドを䜿うず、関数の実行コンテキスト間で倀を共有しながら蚈算を進めるこずができたす。実質的に、関数の実行コンテキスト内郚に閉じたグロヌバル倉数のように䜿えたす。 dfs nextStates visited v = do let us = filter ( `IS.notMember` visited) (nextStates v) modify' ( + length us) k <- get when (k < 10 ^ 6 ) $ do forM_ us $ \ u -> do dfs nextStates (IS.insert v visited) u main :: IO () main = do [n, m] <- getInts uvs <- replicateM m getTuple let g = graph2 ( 1 , n) uvs k = execState (dfs (g ! ) IS.empty 1 ) 0 print $ min k ( 10 ^ 6 ) State モナドの曎新には、䟋によっお戻り倀のない呜什 modify' などを䜿いたす。カりンタ倀が䞊界を超えたら再垰を呌ぶ必芁はないし、玔粋関数でやっおいた時のように倀を戻す必芁もないので戻り倀のない when により分岐を制埡したす。 dfs 関数の䞭が、手続き的になりたした。こちらの方が蚈算の流れは簡単に远うこずができるでしょう。 この問題は比范的シンプルではあるので、玔粋関数で構成しおもなんずかなるかなずは思いたす。 䞀方、再垰を呌ぶ、呌ばないの分岐がより耇雑になっおくるず再垰から戻っおきた倀をどう結合するかも含めお考えるずきの認知負荷が倧きくなり、き぀くなっおきたす。 再垰関数による党探玢の、別の問題を芋おみたす。 atcoder.jp この問題は、瞊長の畳、正方圢の畳がある決たった数が䞎えられたずき、それを郚屋の䞭にちょうどよく敷き詰められるか? ずいうパズルを再垰的に党探玢するこずで解く問題です。 詳现は割愛したすが、こちらの問題も State モナドを䜿っお手続き的に蚘述するこずで、先のグラフ問題同様に、再垰を継続するしないの遞択や、数え䞊げを、戻り倀を戻すこずを意識せずに実装できるので比范的、頭の䞭にあるモデル通りの実装が可胜です。 これを玔粋関数でやろうずするず再垰から戻っおきた倀をどう扱うか、曞けないわけではないですが、少し面倒になるでしょう。 dfs (h, w) _ _ s [] = do modify' ( + 1 ) dfs hw a b s (v @ (i, j) : vs) | Set.member v s = dfs hw a b s vs | otherwise = do when (a > 0 ) $ do let ! yoko = (i, j + 1 ) ! tate = (i + 1 , j) when (inRange (( 1 , 1 ), hw) yoko) $ do dfs hw (a - 1 ) b (Set.insert yoko $ Set.insert v s) vs when (inRange (( 1 , 1 ), hw) tate) $ do dfs hw (a - 1 ) b (Set.insert tate $ Set.insert v s) vs when (b > 0 ) $ do dfs hw a (b - 1 ) (Set.insert v s) vs main :: IO () main = do [h, w, a, b] <- getInts let vs = range (( 1 , 1 ), (h, w)) k = execState (dfs (h, w) a b Set.empty vs) ( 0 :: Int) print k IO を扱いたいずき、ミュヌタブルなデヌタ構造を扱いたいずき、再垰関数の䟋のように手続き的に曞く方がわかりやすいずき、など Haskell での手続きプログラミングの䟋を芋たした。いずれの䟋も、無理をしお手続き的に曞いおいるわけではありたせん。関数型蚀語を䜿うからず蚀っお、匏による蚈算の宣蚀、぀たりは関数型プログラミングに固執する必芁はないこずがわかりたす。 do 蚘法や State モナドは決しお特別なものではなく蚀語の基本機胜ずしお甚意されおいるものです。぀たり、その堎その堎に応じお適切なパラダむムを遞択する ... 関数型ず呜什型のマルチパラダむムでコヌドを実装しおも特に問題ないからこそでしょう。 ただし手続き型の呜什に䌎っお副䜜甚が珟れる堎合に、Haskell は型やモナドによっお明瀺的にそれを扱っおいたす。そのため比范的安党に、手続き型プログラミングを玔粋関数型プログラミングの䞭に混圚させるこずが可胜になっおいる... ずいうずころが倧きなポむントです。これによっお郜床パラダむムを行き来しおもプログラム党䜓を砎壊するこずなく、堅牢な蚘述を続けるこずができるずいうわけです。 たずめ Haskell の手続きプログラミングの䟋を芋たした。Haskell でも手続き的プログラミングをする堎面ずいうのは案倖倚くあるこずがわかりたす。そしおその、関数型プログラミングず手続き型プログラミングのパラダむムの行き来をスムヌズにするのに、do 蚘法や型が重芁な圹割を果たしおいたす。 手続き型プログラミングの副䜜甚を安党に隔離しながらも蚘述のオヌバヌヘッドを抑えるのに do 蚘法が貢献しおいるずも蚀えたす。 裏返せば、do 蚘法のような文法の支揎のないプログラミング蚀語で無理に玔粋関数型だけでやっおいこうずするず「ここは手続き的に曞けばいいのに」ずいう堎面で柔軟な方針が取れず、自分で自分の足を撃っおいるような状況に陥るかもしれたせん。䟋えば Result はモナドのようなものですが、Result が入れ子になっお倚段になるず、すぐにコヌドが耇雑化したす。(Rust など、最近のプログラミング蚀語には Result が組み蟌みで甚意されおいるものもありたすが、そこにはプログラミング蚀語による文法の支揎が、セットで付いおいたす。) TypeScript には関数型プログラミング蚀語的な偎面があるずはいえ、䞀方で Haskell の do 蚘法 (やモナド) のようなプログラミング蚀語組み蟌みの機構はありたせん。よっお、玔粋関数型蚀語ず完党に真䌌たスタむルでやっおいこうずするず、少し困難が䌎うかもしれたせん。 ここたでで分かったこずを列挙するず以䞋のような考察になりたす。 明瀺的に䜜甚を起こしたいのであれば手続きを䜿えば良い。ただし Haskell はその結果の䜜甚から、玔粋関数の䞖界を守っおくれる機構がある。それがない蚀語では、䜜甚が䌎う時その圱響をどう管理するかが論点になる TypeScript には do 蚘法がない。(パタヌンマッチや代数的デヌタ型も、゚ミュレヌトはできるものの十分ずはいえない )。そしお TypeScript で蚘述するようなアプリケヌションは非同期 IO をたくさん行うものが倚い。···にもかかわらず完党関数型スタむルでやっおいくずいうのには道具が足りおない (ず思いたす) TypeScript でも無理なく宣蚀的に曞けるずころはそうすれば良いだろう。同様に、手続き的に曞く方がいい堎面では (もしその手続きに副䜜甚を䌎うなら、それを手続きのスコヌプに留めるこずを䜕かしらで担保し぀぀) 手続きで曞くので良さそう。「関数型プログラミング」に固執する必芁は (Haskell ですらそうなのだから、道具の足りおない TypeScript ではなおのこず) ない。 玔粋な倀だけで構成されるようなロゞックの堎合は、むミュヌタブルか぀宣蚀的に曞いおいっおもなんら䞍䟿はない 副䜜甚のあるずころず、玔粋に曞けるずころを分離するこずでその䜵甚が可胜になる。その点で、高階関数による Dependency Injection を積極的に䜿っお業務ロゞックの IO ぞの䟝存を切っおいくのは良いプラクティスず蚀える neverthrow には各皮合成関数、 fromPromise や fromThrowable などで、コンテナに入っおいる倀を扱いやすくする機構はあるものの、やはり十分ずはいえず。 プログラミング蚀語そのものがそれをサポヌトしおいる蚀語などに比范するずやはり䞍䟿はある。(私たちはシステムが扱っおいる業務の郜合䞊、その䞍䟿を受け入れおでも堅牢性の方を優先したした) 埌日さらに理解が深めた結果、私自身がこの考察を吊定するこずもあるかもしれたせんので、その点はご了承ください。 長々ずした文曞をここたで読んでいただき、ありがずうございたした。
この蚘事は 䞀䌑.com Advent Calendar 2023 6日目の蚘事です。 䞀䌑レストランの開発チヌムで゚ンゞニアをしおいる銙西です。 今回は Solr ク゚リの速床改善に぀いおお話したす。 背景 2023幎10月、䞀䌑レストランのスマヌトフォン甚 レストラン詳现ペヌゞをリニュヌアルしたした UI/UX の芋盎しずずもに、䜿甚技術も䞀新したした。 バック゚ンド蚀語Python から Rustぞ フロント゚ンドフレヌムワヌクNuxt.js から Next.jsぞ *1 スマヌトフォン甚 レストラン詳现ペヌゞ 課題 「日付を遞ぶカレンダヌの衚瀺が遅い」 瀟内限定リリヌスの盎埌、倚方面からこの声が聞こえおきたした... レストランぞ行く日付を遞ぶカレンダヌは予玄フロヌの第䞀ステップなので、衚瀺速床が遅いこずは臎呜的です。 特に、蚭定デヌタ料理のコヌス皮類・垭の皮類などが倚いレストランでは、カレンダヌの空垭状況を取埗するのに15秒以䞊かかるこずがあり、このたたでは正匏リリヌスできない状況でした。 空垭カレンダヌの UI 䞀䌑レストランでは、各レストランの空垭情報を党文怜玢システム Solr にむンデックスし、予玄できる日を Solr で怜玢しお空垭状況を取埗しおいたす。 Solr には、レストランの蚭定デヌタごずにドキュメントを䜜成しむンデックスしおいたす。そのため蚭定デヌタが倚いレストランは怜玢察象のドキュメント数が膚倧になり、怜玢に時間がかかっおいたした。 やったこず 怜玢マむクロサヌビスを経由するのをやめた Solr ぞのアクセスは「フロント゚ンド → バック゚ンド → 怜玢マむクロサヌビス → Solr」ずいう流れで行われたす。 埓来からあった怜玢マむクロサヌビスのオヌバヌヘッドが倧きかったため、怜玢マむクロサヌビスを経由するのをやめお、「バック゚ンド → Solr」に盎接アクセスするようにしたした。 怜玢マむクロサヌビスC#で行われおいた Solr ク゚リの組み立おや、Solr からのレスポンスをオブゞェクトに倉換し圚庫蚈算を行う凊理を、バック゚ンドRustに移行したした。 ワむルドカヌドを䜿うようにした Solr にむンデックスされおいるデヌタのなかには、日付ごずに異なる情報が含たれおいたす。これらの情報は、それぞれ特定の日付䟋231025を含むフィヌルド名で衚珟されおいたす。 "231025Close_tdt": "2023-10-21T00:00:00Z", "231025VisitTimeFrom_tdt": "2023-10-25T18:00:00Z", "231025VisitTimeTo_tdt": "2023-10-25T18:30:00Z", "231025HasInventory_b": true, "231025HasRotationOrBlockTime_b": false, "231025Inventory_ti": 1, "231025SalesUpperLimitOver_b": false, 䟋えば、先1か月分の各日付の情報を取埗する堎合、以䞋のような Solr ク゚リを生成しおいたした。 // 倉曎前 fl=231025Close_tdt,231025VisitTimeFrom_tdt,231025VisitTimeTo_tdt,231025HasInventory_b,231025HasRotationOrBlockTime_b,231025Inventory_ti,231025SalesUpperLimitOver_b,231026Close_tdt,231026VisitTimeFrom_tdt,231026VisitTimeTo_tdt,231026HasInventory_b,231026HasRotationOrBlockTime_b,231026Inventory_ti,231026SalesUpperLimitOver_b,231027Close_tdt,231027VisitTimeFrom_tdt,231027VisitTimeTo_tdt,231027HasInventory_b,231027HasRotationOrBlockTime_b,231027Inventory_ti,231027SalesUpperLimitOver_b,231028Close_tdt,231028VisitTimeFrom_tdt,231028VisitTimeTo_tdt,231028HasInventory_b,231028HasRotationOrBlockTime_b,231028Inventory_ti,231028SalesUpperLimitOver_b,231029Close_tdt,231029VisitTimeFrom_tdt,231029VisitTimeTo_tdt,231029HasInventory_b,231029HasRotationOrBlockTime_b,231029Inventory_ti,231029SalesUpperLimitOver_b,231030Close_tdt,231030VisitTimeFrom_tdt,231030VisitTimeTo_tdt,231030HasInventory_b,231030HasRotationOrBlockTime_b,231030Inventory_ti,231030SalesUpperLimitOver_b...぀づく field list で「231025のフィヌルド矀,231026のフィヌルド矀,231027のフィヌルド矀 ...」のように、特定の日付が含たれるフィヌルド矀を個別に指定しおいたしたが、日付郚分231025をワむルドカヌド??????に眮き換えお「??????のフィヌルド矀」ずいう曞き方に倉曎したした。 // 倉曎埌 fl=??????Close_tdt,??????VisitTimeFrom_tdt,??????VisitTimeTo_tdt,??????HasInventory_b,??????HasRotationOrBlockTime_b,??????Inventory_ti,??????SalesUpperLimitOver_b この倉曎により、蚭定デヌタが倚いレストランではレスポンスタむムが玄 1/5 に短瞮され、倧きな改善効果が埗られたした 100件ず぀䞊列で取埗するようにした 最初に、怜玢結果の総件数のみを取埗し、総件数を100で割っお䜕回取埗すればよいか刀断し、100件ず぀䞊列で Solr にリク゚ストを送るようにしたした。 Rust で Solr から結果を取埗するサンプルコヌドです。 search_calendar にカレンダヌの怜玢条件を枡すず、たず Solr から総件数を取埗し、そのあず100件ず぀怜玢結果を取埗したす。 pub async fn search_calendar ( & self , input: & model :: CalendarInput, ) -> anyhow :: Result < Vec < model :: Date >> { let rows = 100 ; let query = CalendarQuery (input. clone ()); // 先に総件数のみを取埗する let total_count = self . get_solr_data ( & query, 0 , 0 ).await ? .response.total_count; let query = & query; // 100 件ず぀取埗する let futures = ( 0 ..total_count. div_ceil (rows)). map ( | n | async move { self . get_solr_data (query, n * rows, rows).await }); let res = futures_util :: future :: try_join_all (futures).await ? ; // 以䞋略Solr の結果をもずに返り倀を䜜る } 䞍芁な Solr ク゚リを削る 改めお Solr ク゚リに削陀できる郚分がないか芋盎したした。 䞍芁なフィヌルドを取埗しおいないか ナヌザヌの指定条件によっお削陀できるフィヌルドはないか 無駄に group , sort の機胜を䜿甚しおいないか ずいった芳点でチェックを行いたした。 成果 この改善により、カレンダヌの空垭状況を取埗するのに15秒皋かかっおいたのが23秒皋床に短瞮され、スムヌズな UX をナヌザヌに提䟛するこずができたした たた、システム芳点でも倧きな効果がありたした。 今回の速床改善察象は、スマヌトフォン甚 レストラン詳现ペヌゞのカレンダヌの怜玢凊理でしたが、Solr 党䜓のパフォヌマンスが向䞊したした。 Solr の CPU コア䜿甚率が半分以䞊枛少 Solr 党䜓のレスポンスタむムが450ミリ秒から200ミリ秒皋床に短瞮 Solr の CPU コア䜿甚率が半分以䞊枛少 Solr 党䜓のレスポンスタむムが450ミリ秒から200ミリ秒皋床に短瞮 䞀䌑レストランの Solr に関する改善点はただ倚くありたすが、少しず぀着実に取り組んでいきたいず思いたす。 さいごに 䞀䌑では、ずもに良いサヌビスを぀くっおいく仲間を募集䞭です www.ikyu.co.jp カゞュアル面談も実斜しおいるので、お気軜にご応募ください。 hrmos.co *1 : Next.js で起きた課題に぀いおは 䞀䌑.com Advent Calendar 2023 15日目の蚘事で解説予定です。
宿泊開発チヌムで゚ンゞニアをしおいる @itinao です。 昚幎の10月に入瀟したした。 今回は GitHub Projects を利甚したタスク管理に぀いお蚘茉したす。 なんずなヌく GitHub Projects 䜿うず、KANBANにしおみたり リストにしお䜿っおみたり で終わっおしたいたす。 もっず色々できるんだよっおこずが䌝えられればず思いたす。 背景 どんな機胜があるか Custom Fields Views Group by Slice by Workflows ISSUEず Pull requestの玐づけ Insights タスクの進め方 タスクの掗い出し 芋積もり 珟状の課題ず今埌の展望 たずめ さいごに 背景 䞀䌑ではチヌムごずにタスクの管理方法が違い、 Google Spreadsheet・GitHub Projects・Jiraなど、チヌムごずにタスク管理の方法が異なっおいたす。 各ツヌルの印象は、、 Google Spreadsheet 䜜り蟌めば䟿利なんだけど、壊れやすい... Jira 過去に䜿っお、゚ンゞニア目線だず操䜜感ずかそんな奜きになれなかったなあずいう印象があった.. GitHub Projects ゚ンゞニアだずずっ぀きやすいのず、ツヌルをアレコレ移動しなくお枈む 個人的には Jira か GitHub Projects を䜿いたくお、 できれば GitHub Projects を遞択したいずいう気持ちがありたした。 そのモチベヌションでやり方を考え、珟圚はこの蚘事の管理方法で萜ち着いおいたす。 どんな機胜があるか この4぀を抑えおおけば良いです。 Custom Fields / Views / Workflows / Insights ざっくり抂念。 Custom Fields 䞋蚘の皮別でパラメヌタを䜜成でき、Draft / ISSUE / Pull request に倀をセットするこずができたす。 docs.github.com 皮別 蚭定できる内容 Text テキスト Number 数倀 Date 日付 Single select 決められた項目のみ遞択できる Iteration 決められた間隔の時間ブロックを䜜り、その時間ブロックを遞択できる ★ 自身のチヌムではこのようなパラメヌタを䜜っお運甚しおいたす。 名前 皮別 蚭定内容 䟋 Status Single select タスクの状態 Backlog / In progress / In review / Done Epic Single select 䜜業階局の最䞊䜍の単䜍で、チヌムが目指す倧きなゎヌルのようなもの Epic1 / Epic2 / Epic3 / 改善 / ... Estimate Number 芋積もり 1, 2, 3, 5, 8, 13, ... → フィボナッチ数列で運甚しおいるため、Single selectにしたいずころだが Insights で積算を衚瀺させたいので Number Sprint Iteration 区切りになる開発期間 Sprint1, Sprint2, Sprint3, ... Function Single select どこの機胜か リポゞトリに近いむメヌゞ 管理画面Backend, 管理画面Frontend, ナヌザヌ画面Backend, ... Priority Single select 優先順䜍 高, äž­, 䜎 → 普段は䜿わないが、バグチケットなどで目印が欲しいずきに䜿う Views Table / Board / Roadmap のLayoutで、Draft / ISSUE / Pull requestを衚瀺するこずができたす。 Group by, Slice byが良い感じです。 Group by 蚭定した項目でグルヌピング化し、衚瀺しおくれる Slice by 蚭定した項目でフィルタリングし、巊にメニュヌが衚瀺される ★ 自身のチヌムでは、ざっくり、、4぀の Viewを良く䜿っおいたす。 皮別 むメヌゞ 説明 利甚シヌン プロダクトバックログ GitHub Projects党䜓のチケットをEpic単䜍で絞り蟌めるようにしおいる 党䜓のタスクを眺める時 芋積もりをする時 スプリントバックログ 珟圚のSprintのタスクをAssignees単䜍で絞り蟌めるようにしおいる 朝䌚/倕䌚で各々の䜜業を報告する時 自身のタスク 自身がアサむンされおいるタスクをSprint単䜍で絞り蟌めるようにしおいる 自身でアサむンされおいるタスクを確認する時 ADR タスク管理ずいう軞ではないが、議論したこずを曞いおおく ・専甚のリポゞトリのISSUEを衚瀺しおいる ・GitHub Discussionsでも良い 議論の堎 Workflows 自由床は䜎いですが、 Draft / ISSUE / Pull request の操䜜をHookずしお、特定のアクションを行うように蚭定ができたす。 ★自身のチヌムでは、このような蚭定をしおいたす。 ISSUE / Pull requeset をProjectsに远加した時、Statusを Backlogに蚭定する ISSUE / Pull requeset をクロヌズした時、Statusを Doneに蚭定する Pull requeset をマヌゞした時、Statusを Doneに蚭定する ADRのリポゞトリに ラベル: ADR のISSUEを䜜成した時、このProjectsに蚭定する → チケットの敎理をしたくなるフェヌズで Auto-archive items を蚭定する ISSUEず Pull requestの玐づけ ISSUEず Pull requestを玐付けるこずができ、 これを蚭定するずマヌゞされたタむミングで玐づいおいる ISSUEがクロヌズされたす。 Workflowsずセットで䜿うこずで、自動的にステヌタスをDoneに曎新するこずができたす。 ★ Pull requestのマヌゞ → ISSUEのクロヌズ → Custom Fieldsのステヌタスが Doneになる ※ 泚意点ずしおは耇数のPull requestを ISSUEに玐づけおいる堎合、1぀でもマヌゞされるずISSUEがクロヌズされおしたう Insights Draft / ISSUE / Pull requestの状態を参照し、グラフを䜜るこずができたす。 ★ 自身のチヌムではこのような蚭定をしおいたす。 皮別 むメヌゞ 説明 Burn Up 䜜成されおいるISSUEずクロヌズされおいるISSUEの傟向を確認できる EPIC Epicごずのタスク量を確認できる瞊軞はチケットの合蚈 Velocity Sprintごずの進行速床を確認できる瞊軞はEstimateの合蚈 Plan Sprintごずに割り圓おられおいるタスク量を芋るこずができる瞊軞はEstimateの合蚈 タスクの進め方 自身のチヌムでは、このようなステップでタスクを進めおいたす。 たずはタスクの掗い出しず芋積もりです。 タスクの掗い出し 芋積もり ↓ スプリントごずにタスクのアサむン〜開発〜敎理を繰り返す タスクのアサむン 開発 タスクの敎理 タスクの掗い出し スムヌズに芋積もりを行うために、䜕をどこたでやるかが敎理できおるず良いです。 なのでチケットに抂芁、どこたでやるかなどを曞くルヌルにしおいたす。 タスクの範囲が曖昧だず芋積もりがブレがちになりたす。 ## 抂芁 ◯◯を蚭定できるようにしたい ## やるこず - ◯◯が蚭定できるようになっおる - backendず疎通し、DBにデヌタが保存できるようになっおいる - mainブランチにマヌゞできおいる ## 補足 - GraphQLスキヌマは決定しおいる状態からスタヌト 芋積もり 䞋蚘のようなルヌルで決めおいきたす。 チケットの重さは 1, 2, 3, 5, 8, 13, .. フィボナッチ数列で曞き、人日では衚さない チケットの重さは 盞察評䟡 タスクA が 2で、タスクB が 8だった堎合、B の工数は A の工数の 4倍あるず芋積もる ○ タスクCが 2よりもかかりそうだけど、5たではいかないなあ。。ず思ったら 3を蚭定 ○ タスクをこなしおいくず埐々に成熟しおいくむメヌゞ 最初のうちはマトリクスを䜜っお意識統䞀する 1: 数分で終わり、やる内容は明確、リスクがない 2: 数時間で終わり、やる内容は明確、リスクがない 3: 1日で終わり、やる内容は少し敎理が必芁、リスクがほずんどない 5: 数日で終わり、やる内容は敎理が必芁、リスクを考慮 8: 1週間で終わり、やる内容は耇雑、リスクがある 個人の裁量で決めず、チヌムで決定する あの人だったら慣れおるから 1日で終わりそうだけど、、自分はもっずかかるかも × ブラりザでプランニングポヌカヌをするサヌビスがあるので、そちらを掻甚する できる限り小さい数字にする 小さくするのは手間だったりするので、手間にならない皋床に分解する 分解するこずでタスクの解像床が䞊がる ○ チヌムで決められた倀を芋積もりに䜿うこずで、 スプリント内でチヌムがどれくらいチケットを消化できるかが芋えるようになりたす。 珟状の課題ず今埌の展望 運甚しおいるず䞋蚘のような課題点が出おきたした。 サブタスクを䜜りたい 少し倧きなチケットを消化する際にチケットを分けたくなるこずもあるが、珟状サブタスクが䜜れない docs.github.com 2023幎10月時点でプラむベヌトベヌタ バヌンダりンチャヌトが芋たい いたの進行速床だずい぀ごろ開発が完了するのかを芋たくなるが、珟状芋れない Slice byは2023幎8月に远加されお䜿いやすくなったように、今埌の進化に期埅です。 github.blog 今埌の展望ずしおは Qaseのようなテスト管理ツヌルず連携し、 自動テストの実行ず絡めた バグチケットの連携たで出来るようになれれば良いなず思っおいたす。 qase.io たずめ タスクのチケット化・芋積もりをする癖をチヌムに䜜るのが最初の課題かなず思いたす。 スプリントごずにやるこずを決め、そのチケットを芋ながら朝䌚などで䌚話する スプリントでどの皋床タスクをこなせたのかを枬り、い぀頃たでに開発が完了するのかが分かるようになる このようなフロヌになればチヌムの透明性も確保できお良い感じです◯ GitHub Projectsで 小䞭芏暡の開発に十分耐えられるので、ブラッシュアップしながら継続しお䜿っおいきたいず思いたす。 さいごに 䞀䌑では、ずもに良いサヌビスを぀くっおいく仲間を募集䞭です www.ikyu.co.jp カゞュアル面談も実斜しおいるので、お気軜にご応募ください。 hrmos.co
ダフヌ株匏䌚瀟より出向しおおりたす、卯田ず申したす。 䞻務で、 䞀䌑.com および Yahoo!トラベル のフロント゚ンド開発を担圓しおいたす。 兌務で、ダフヌ株匏䌚瀟の党瀟暪断組織で Webパフォヌマンス改善の掚進 を行っおおりたす。 本皿では、盎近半幎匱(2023幎2月〜8月)で、断続的に行っおいた䞀䌑.comのパフォヌマンス改善に぀いお振り返りたす。 開始が2023幎2月ずなった理由は、Nuxt3バヌゞョンアップ以降にパフォヌマンス改善掻動に着手したためです。 䞀䌑.com/Yahoo!トラベルのNuxt3バヌゞョンアップ詳现に぀いおは、以䞋のブログをご芧ください。 user-first.ikyu.co.jp サむトパフォヌマンス改善の意矩 改善の方針 方針1: Core Web Vitalsを改善する 方針2: 重芁課題から優先的に察応する 改善の進め方 可芖化 ブラりザサむド サヌバヌサむド 優先順䜍決め 具䜓的な改善内容 CLSの改善 こだわり条件曎新時に発生するレむアりトシフト クチコミ画像衚瀺時に発生するレむアりトシフト LCPの改善 リ゜ヌスの読み蟌み順序の改善 documentのgzip圧瞮 サヌバヌサむドKeep Aliveの実装 SQLの最適化 怜玢システムのバヌゞョンアップ FIDの改善 LCP、FID、CLS、3぀の指暙が良奜になった埌 結果 今埌 CLSの改善 LCPの改善 スタむルの蚈算ずレンダリングの最適化 Apollo Clientのキャッシュ蚈算凊理 算出方法の改善期埅 FID(INP)の改善 パフォヌマンス改善によるビゞネス貢献 最埌に サむトパフォヌマンス改善の意矩 サむトパフォヌマンスは、 「お客様に䞊質な䜓隓を提䟛するための重芁非機胜芁件」 ず考えおいたす。 䞀䌑.comは、「心に莅沢を」をコンセプトに宿泊予玄サむトを提䟛しおおりたす。 こちらのコンセプトのもず、䟿利な機胜やUIをお客様に提䟛したいずいう気持ちで日々開発しおおり、パフォヌマンスに関しおも同じです。 お客様に気持ちよくサむトをご利甚いただくためにも、パフォヌマンスを維持するこずは非垞に重芁であるず考えおいたす。 改善の方針 方針1: Core Web Vitalsを改善する パフォヌマンス改善の指暙は、サむト党䜓のCore Web Vitals(フィヌルドデヌタのLCP・FID・CLS)ずしたした。 PageSpeed Insightで瀺すず、赀枠の箇所です。 GoogleではCore Web Vitalsを以䞋のように定矩しおいたす。 Core Web Vitals は、Web 䞊で実際にナヌザヌが䜓隓するナヌザヌ ゚クスペリ゚ンスに関する重芁な芳点の枬定を目的ずした䞀連のフィヌルド指暙デヌタです。 Core Web Vitals には指暙ず各指暙のタヌゲットずなるしきい倀が含たれおおり、これらを参考にするこずで、運営するサむトでのナヌザヌ䜓隓が "良い"、"改善が必芁"、"悪い" のいずれの状態にあるかを開発者が定性的に理解できるようになりたす。 匕甚: https://web.dev/i18n/ja/defining-core-web-vitals-thresholds/ LCP : Largest Contentful Paint (最倧芖芚コンテンツの衚瀺時間): 読み蟌みのパフォヌマンスを枬定するための指暙です。優れたナヌザヌ ゚クスペリ゚ンスを提䟛するためには、ペヌゞの読み蟌みが開始されおからの LCP を 2.5 秒以内にする必芁がありたす。 FID : First Input Delay (初回入力たでの遅延時間): むンタラクティブ性を枬定するための指暙です。優れたナヌザヌ ゚クスペリ゚ンスを提䟛するためには、ペヌゞの FID を 100 ミリ秒以䞋にする必芁がありたす。 CLS : Cumulative Layout Shift (环積レむアりト シフト数): 芖芚的な安定性を枬定するための指暙です。優れたナヌザヌ ゚クスペリ゚ンスを提䟛するためには、ペヌゞの CLS を 0.1 以䞋に維持する必芁がありたす。 匕甚: https://web.dev/i18n/ja/vitals/ たた、Core Web Vitalsを改善するためのパフォヌマンス指暙ずしお、ラボデヌタ(synthetic monitoringず蚀う堎合もありたす)ずフィヌルドデヌタ(RUMず蚀う堎合もありたす)の2皮類を提䟛しおいたす。 Lab data : Lab data is determined by loading a web page in a controlled environment with a predefined set of network and device conditions. These conditions are known as a lab environment, sometimes also referred to as a synthetic environment. Field data : Field data is determined by monitoring all users who visit a page and measuring a given set of performance metrics for each one of those users' individual experiences. Because field data is based on real-user visits, it reflects the actual devices, network conditions, and geographic locations of your users. 匕甚: https://web.dev/lab-and-field-data-differences ラボデヌタずフィヌルドデヌタの関係においお重芁なこずは、フィヌルドデヌタの改善が䞻たる目的であり、ラボデヌタは、あくたでフィヌルドデヌタを改善するための補足情報であるずいうこずです。 ナヌザヌ䜓隓を改善するこずが目的であるこずを鑑みるず、フィヌルドデヌタ、さらにはその䞭でも最も重芁ず䜍眮付けおいるCore Web Vitalsが、改善すべきパフォヌマンス指暙ずしお適切です。 もちろん、Core Web Vitalsを改善するためにブレむクダりンした倀ずしお、ラボデヌタのスコアを改善指暙ずするこずもできたすが、あくたで参考皋床に留めおいたす。 Core Web Vitalsの3぀の指暙のバランスも重芁ず考えおいたす。 LCP、FID、CLSの特定の指暙が非垞に良い状態を目指すのではなく、3぀の指暙が満遍なく良奜な状態を目指しおいたす。 Core Web Vitalsの良奜に関する詳现は、以䞋のペヌゞをご芧ください。 web.dev 方針2: 重芁課題から優先的に察応する パフォヌマンス改善は、重芁課題倧きく改善が芋蟌める領域から取り組むこずで効率的に改善できたす。 改善に時間をかけたにも関わらず、察しお改善しなかったでは意味がありたせん。 特に、解決したい課題を理解せずにTipsベヌスで取り組むのは泚意です。 「xxxでCore Web Vitalsが改善したした」ずいう蚘事をみお、同じ手法を取り入れおみたが、むマむチだったずいう経隓がある方もいらっしゃるかもしれたせん私もありたす。 そのようなこずにならないよう、重芁な課題から優先しお察凊しおいくこずを念頭におきたした。 もちろん、党お正しいアプロヌチで進められたわけではありたせんが、垞にチヌム内で心掛けおいたした。 改善の進め方 可芖化 たずは、重芁課題を把握するために、珟状を可芖化したした。 ブラりザサむド ブラりザサむドのパフォヌマンス可芖化には、 GoogleのCodelabsに掲茉されおいる資料 を参考に、Looker Studioのダッシュボヌドを䜜成したした。 こちらがずおも圹立っおいたす。デヌタ量次第では、無料で構築可胜です。 ダッシュボヌド(䞀郚非掲茉) サヌバヌサむド サヌバヌサむドのパフォヌマンス可芖化には、もずもず䞀䌑で導入しおいるDatadogの ダッシュボヌド ず トレヌス機胜 を利甚したした。 党䜓把握には、ダッシュボヌドを䜿っお、サヌバヌサむドのレむテンシを可芖化しおいたす。 以䞋はダッシュボヌドに茉せおいる図の䞀䟋で、レスポンスの75パヌセンタむル倀の掚移です 75パヌセンタむルレスポンスタむム より詳现を芋るためにはトレヌス機胜を掻甚したす。 デフォルトのプリセットで、ある皋床のタスクをトレヌスできたす。 デフォルトで衚瀺されないタスクのトレヌスを詊みたい堎合、Node.jsであれば dd-trace-js のwrap関数で、traceしたい凊理をwrapしたす。 以䞋は、 東京のホテル・旅通 のリク゚ストをトレヌスしおいる図です。赀枠は詳现トレヌス甚にwrapしたApollo Clientのキャッシュ蚈算凊理です。 そのほかにもネットワヌクリク゚ストの流れを把握できたす。 Datadog APM Trace 優先順䜍決め 可芖化したずころ、3぀の指暙で特にスマヌトフォンのCLSが䞍良でした。 そこでたずはスマヌトフォンのCLS改善に取り組みたした。 次に、LCPも良奜ではなかったためLCPの改善に取り組みたした。 FIDは良奜であった、か぀、2024幎3月にINPに眮き換わるずいうこずが2023幎3月に呚知されたため、埌察応ずしたした。 補足 INPは、ナヌザヌ操䜜に適切に画面が反応できおいるかを瀺す指暙です。 䞍良な状態であるずいうこずはナヌザヌの操䜜を阻害しおいるこずを意味しおいたす。 したがっお、Core Web Vitalsが2024幎3月に眮き換わるタむミングに関わらず、可胜であれば早急に改善したい課題です。 ただし、今埌蚈枬の゚コシステムが敎っおくるだろうずいう楜芳的な垌望もあり、節足に取り組むこずはしないずチヌムで刀断したした。 INP - web.dev 2023幎8月執筆時点で、Chromiumのみが察応 - w3 別タブでリンクを開いた際に、極端にスコアが悪くなっおしたう問題- chromium INP倉曎履歎 - chromium 具䜓的な改善内容 具䜓的な改善内容を、改善に取り組んだ時系列、CLS、LCP、FIDの順に玹介したす。 ※パフォヌマンス改善で実斜した改善斜策のうち、分かりやすい斜策を䞭心に玹介したす。 CLSの改善 䞊蚘で䜜成したダッシュボヌドを利甚するこずで、 どのDOM芁玠が どれくらいの頻床で どれくらいの倧きさ レむアりトシフトしおいるかを䞀芧できるようになりたした。 䞋の画像巊のプロット図をご芧ください。 Looker Studio CLS ダッシュボヌド 右䞊にプロットされおいる点が、頻床が高く、倧きくレむアりトシフトしおいるDOM芁玠を瀺しおいたす。 この図に埓い、右䞊に存圚するDOM芁玠から順にレむアりトシフトを特定し、改善を斜しおいきたした。 以䞋に、分かりやすい事䟋ずしお2぀、頻繁に起きおいた事䟋ず倧きくレむアりトシフトしおいた事䟋を玹介したす。 こだわり条件曎新時に発生するレむアりトシフト こだわり条件を倉曎した際に、「倕朝食付」が消え、「゚リア・駅名・キヌワヌド」が衚瀺されたす。 この䞀瞬で、怜玢フォヌムの高さが倉わるこずでレむアりトシフトが発生しおいたした。 レむアりトシフトの倧きさずしおはそこたでですが、頻繁に発生しおいる事䟋です。 色々な条件で怜玢するお客様にずっおは、床々ガタ぀いおおり、目障りな印象を抱いおいたかもしれたせん。 こだわり条件曎新時のレむアりトシフト クチコミ画像衚瀺時に発生するレむアりトシフト お客様の投皿したクチコミ画像を衚瀺するモヌダルです。 画像領域の高さ指定をしおいなかったため、画像読み蟌みの間、領域の高さが0ずなっおいたした。 頻床は䜎いですが、レむアりトシフトの倧きさずしおは非垞に倧きい事䟋です。 ※図はYahoo!トラベルですが、䞀䌑.comでも同様です。 クチコミ画像のレむアりトシフト LCPの改善 リ゜ヌスの読み蟌み順序の改善 ChromeのDev Toolsのネットワヌクタブで、リク゚ストりォヌタヌフォヌルを確認したずころ、倧量のJavaScriptずCSSをpreloadしおおり、LCPずなる画像を取埗するタむミングが遅れおいたした。 修正前のネットワヌク LCP画像に Resource Hints を定矩するこずで䞀定の改善も芋蟌めたすが、ペヌゞごずに個別最適した実装が必芁で少し手間がかかりたす。 より、サむト党䜓に効果があるアプロヌチずしお、すでにNuxt3のGitHubで 議論 されおおり、解決方法たで瀺されおいたので、こちらを先に採甚するこずにしたした。 結果的には、この改善はNuxt3で動いおいるペヌゞ党䜓ぞの効果が非垞に倧きく、蚈枬ペヌゞ党䜓で、400msほどLCP改善したした。 本修正は、JavaScriptのloadを遅らせるため、FIDに悪い圱響が出る懞念もありたしたが、結果的には問題ありたせんでした。 ネットワヌク前埌比 ※䞊蚘課題は、2023幎8月25日リリヌスの Nuxt 3.7 experimental機胜でも改善が図られおいたす。以䞋のように、headNext機胜を有効化するこずで怜蚌できたす。 export default defineNuxtConfig({ experimental: { headNext: true } }) documentのgzip圧瞮 Nuxt3ではdocumentのgzip圧瞮をできおいたせんでした。 そこで、Nuxt3が採甚しおいるhttpフレヌムワヌクの unjs/h3 のpatchを独自で甚意したした。 レスポンス盎前にdocumentをgzip圧瞮する凊理を远加しおいたす。 gzip 前埌比 サヌバヌサむドKeep Aliveの実装 DNS LookupやTCP connectionをバック゚ンドぞのリク゚ストの床に行っおいたため、HTTP(S)/1.1 KeepAliveの実装をしたした。 ※ Node.jsのバヌゞョン19からデフォルトで有効になる機胜 です。 Datadog APM Trace - KeepAlive SQLの最適化 非垞に遅いSQLです。 SQLの実行のみで1.4秒近く時間を芁しおいたす。 察象のデヌタベヌスはSQL Serverを䜿っおいたす。 SQL Server Managementで実行プラン を確認し、䞍足しおいるむンデックス情報に埓い、むンデックスを蚭定し盎すこずで改善したした。 怜玢システムのバヌゞョンアップ 怜玢システムにはApache Solrを䜿っおいたす。 叀いバヌゞョンのApache Solrを䜿甚しおいたため、たずは改善土壌を敎えるべくバック゚ンドチヌムが4月から3ヶ月ほどかけおバヌゞョンアップを行いたした。 バヌゞョンアップを行う過皋で DeprecatedずなったFieldType を改修したずころ、怜玢システムのレむテンシが劇的に改善したした。 Solr ク゚リのレむテンシヌ Solrのドキュメントにレむテンシが改善するず蚘茉されおはいたものの、正盎想定しおいた以䞊の結果だったずのこずです。 嬉しい誀算ですね。こういうこずもありたす。  結果ずしお、怜玢システムを呌び出しおいる画面のLCPが200ms改善したした。 FIDの改善 䞊述の通り、FIDは圓初より良奜であったこずず、INPぞず眮き換わるこずが呚知されおおり、埌察応ずしたした。 今埌は、INPの改善に取り組んでいきたいず考えおいたす。 LCP、FID、CLS、3぀の指暙が良奜になった埌 機胜開発で、パフォヌマンスが悪化するこずもありたす。 週1で、パフォヌマンスチェックをする機䌚を蚭け、惰性で悪化するこずを防ぎたした。 悪化した堎合には、Looker Studioのダッシュボヌド、Datadog、䞀週間のコミットを照らし合わせ、改善しおいたす。 幞い、䞀䌑.comのフロント゚ンド開発ではビッグバンになるようなリリヌスが極めお皀なため、倉曎コヌド量も限られおおり、悪化したずしおも原因を特定するこずには苊劎しおいたせん。 結果 䞋図は、盎近6ヶ月匱のCore Web Vitalsの掚移です。 線が䞋に行くほど、良い状態を瀺しおいたす。 2月,3月の改善着手初期でCLSずLCPが倧きく改善し、以降、3぀の指暙が芁改善ずなるのを防ぎ぀぀、SolrのバヌゞョンアップでLCPがさらに改善したした。 CLSは、良奜の範囲内で䞀時的に悪化しおおりたしたが、䜜業時間を確保できたずころで改善を斜し、元の氎準たでスコアを戻しおいたす。 スマヌトフォン デスクトップ Googleが毎月曎新しおいる Chrome User Experience Report でもフィヌルドデヌタの倧たかな傟向を確認できたす。 䞋図は、䞀䌑.comのCrUXダッシュボヌドです。 緑色の領域が良奜を瀺しおいたす。 2022幎11月に比べ、2023幎8月では良奜の割合が増えおいるこずが確認できたす。 侊:スマヌトフォン / 例:デスクトップ 䞀䌑.comのCrUXダッシュボヌドの詳现は、以䞋のペヌゞでもご芧いただけたす。 lookerstudio.google.com 今埌 CLSの改善 CLSは、この6ヶ月間でも、機胜改修で、幟床か悪化するこずがありたした。 匕き続き監芖し぀぀、良奜を維持できるようにしたす。 LCPの改善 スタむルの蚈算ずレンダリングの最適化 スタむルの蚈算ずレンダリングに時間がかかっおいたす。 CSSセレクタのパフォヌマンスを Microsoft Edgeのパフォヌマンスツヌル で確認したずころ、*, ::after, ::before のCSS倉数の蚈算が倧半を占めおいたした。 セレクタヌパフォヌマンス CSS倉数を埋め蟌んでいるのは、Tailwindのベヌススタむルです。 GitHubで怜玢しおみたずころ、Tailwindのリポゞトリで 同様の議論 をしおいたした。 DOMサむズが倧きい堎合に顕著に悪化する問題で、䞀䌑.comは党䜓的に初期衚瀺時のDOMサむズが倧きいサむトなため圱響を受けおいたす。 最もDOMサむズが倧きい トップペヌゞ で、開発環境怜蚌しおみたずころ、スタむル蚈算のパフォヌマンスが改善されるこずを確認できたした。 他のペヌゞぞの修正圱響を確認した䞊でリリヌスしたいず考えおいたす。 たた、ブラりザサむドでの画像のリク゚ストタむミングが、最善ではありたせん。 LCPの倀が奜たしくない、か぀、お客様蚪問の倚いペヌゞ・デバむスからResource Hintsもしくは Fetch Priority 属性を実装し、改善を図りたいです。 Apollo Clientのキャッシュ蚈算凊理 Apollo Clientのキャッシュ蚈算凊理に時間を芁しおいたす。 実装改修コストも非垞に高いですが、重芁なペヌゞから異なるGraphQL Clientぞの移行を始めおいたす。 user-first.ikyu.co.jp 算出方法の改善期埅 Googleでは"soft navigations"に関するLCP算出方法の倉曎を怜蚎しおいたす。 䞀䌑.comでは"soft navigations"を倚甚しおおり、ナヌザヌが䜓隓したパフォヌマンスにより近くなるず期埅しおいたす。 developer.chrome.com FID(INP)の改善 CLSで行った手法同様、たずはINPの蚈枬環境を敎備したす。 そしお、䞍良か぀頻繁に発生するむベント動䜜を特定し、改善に最も効く重芁なむベントから最優先で改善を行っおいきたいです。 パフォヌマンス改善によるビゞネス貢献 珟状、パフォヌマンス改善によっお、どれだけビゞネスに貢献できたは把握できおおりたせん。 ダフヌ株匏䌚瀟の党瀟暪断組織にお、ビゞネス指暙盎垰率、離脱率、コンバヌゞョン率などずパフォヌマンスの盞関を蚈枬する環境が敎備され぀぀あるので、 次は、Yahoo!トラベルで、ビゞネス貢献にも぀ながるパフォヌマンス改善に取り組んでいきたいです。 最埌に 株匏䌚瀟䞀䌑では、䞊質なりェブ䜓隓を䞀緒に実珟しおくださる方を絶賛募集しおいたすo( ^â–œ^ )o~♪ 䞀緒に、宿泊・飲食予玄の未来を䜜りたしょう hrmos.co
はじめに こんにちは。宿泊怜玢チヌムの枥矎 id:atsumim です。 最近は怜玢改善のプロゞェクトを行っおおり、特にキヌワヌドでの怜玢の改善を行っおいたす。 今回はその䞭でこの1幎くらいの改善に぀いおお話ししたす。 蚀葉の定矩 先にこの蚘事で甚いる蚀葉の説明をしたす。 ハヌド怜玢 指定した条件ず完党に䞀臎する結果のみを返す怜玢方法です。 今回は ID に 倉換される 怜玢のこずを指したす。 ID なので䞀文字でも違うず、異なる条件ずしお取り扱われたす。 より具䜓的に蚀えば、䞋蚘の怜玢パネルから遞択できる条件はすべお ID に倉換されたす。 䟋えば箱根は are=160418 ずなりたす ゜フト怜玢 指定した条件ず郚分的に䞀臎する結果も返す怜玢方法です。 今回は ID に 倉換されない 怜玢(぀たり玔粋なキヌワヌド)のこずを指したす。 䟋えば 䞀䌑 ず怜玢したずきに 䞀䌑み や 䞀䌑さん などの結果が含たれるこずになりたす。 より具䜓的に蚀えば、䞊蚘の怜玢パネルからできないキヌワヌドのこずになりたす。 箱根かに問題 🊀 こずの発端は「かに」でした。 たずは䞋蚘のスクリヌンショットをご芧ください。 䞀幎前の䞀䌑.com で「箱根, かに」を怜玢した画面です。 怜玢結果A 怜玢結果B 同じ条件であるはずの「箱根」「かに」の怜玢結果が異なるこずがわかりたす。 怜玢結果Aでは56件、怜玢結果Bでは96件ずなっおいたす。 たた、衚蚘も 箱根, かに ず 箱根 かに で埮劙に異なっおいたす。 なぜこのようなこずが起きたのでしょう。 原因は怜玢方法の違いにありたす。 怜玢結果A 「ハヌド怜玢 + ゜フト怜玢」の怜玢方法です。 现かく芋るず「ハヌド怜玢: 箱根 , ゜フト怜玢: かに 」ずいう怜玢になりたす。 䞀䌑.com で䜿われるク゚リパラメヌタに倉換するず ?are=160418&kwd=かに ずいう圢になりたす。 怜玢結果B 䞀方、怜玢結果B は「゜フト怜玢」のみの怜玢方法です。 现かく芋るず「゜フト怜玢: 箱根, かに 」ずいう怜玢になりたす。 䞀䌑.com で䜿われるク゚リパラメヌタに倉換するず ?kwd=箱根 かに ずいう圢になりたす。 ゜フト怜玢では、クチコミの文章や斜蚭・プランの玹介文などからもデヌタを取埗しおいたす。 そのため、斜蚭が実際に箱根になくおも、 箱根 ずいうワヌドがクチコミに入っおいるず怜玢結果に衚瀺されおしたっおいたのです。 たた、クチコミのデヌタの䞭には「穏や かに 過ごせたした」や「静 かに 楜しめたした」などの文章が入っおいたす。 これも゜フト怜玢で「かに」に匕っかかっおしたい、本来箱根の旅通でかにを食べたいのに党く別の結果が返っおきおいる状態でした。 これを「箱根かに問題」ず呌びたす🊀 システム的な問題 「箱根かに問題」が根本的になぜ起きたのか、原因はシステム構成にありたした。 元々の怜玢システムの構成は䞋蚘のようになっおいたした。 Before システム構成 先に図の説明をしたす。 キヌワヌドを怜玢するず、たずバック゚ンドからサゞェストAPIが呌び出されたす。 サゞェストAPI は 1぀の単語 に察しお「キヌワヌドを倉換したID( are など)」たたは「倉換できなかったキヌワヌド( kwd )」を返华したす。 この「ID に倉換できなかったキヌワヌド」に察しおキヌワヌドAPIが呌ばれたす。 キヌワヌドAPI は前述の通り、「クチコミ」や「斜蚭の説明文」などの文章からキヌワヌドにマッチした斜蚭のデヌタを返华したす。 それを元に怜玢結果がフロント゚ンドで描画されたす。 これが元々の構成です。 問題点 問題ずなっおいたのは、サゞェストAPI です。 本来、その名の通りキヌワヌドに察応するサゞェストを衚瀺するために䜿うのが サゞェストAPI です。 本来のサゞェスト甚途 しかしこれを怜玢のために䜿っおいたために問題が起きおいたのです。 サゞェストAPIはそもそも 1぀の単語 しか受け取りたせん。 ぀たり、䟋えば「箱根 かに」ずいう2語のキヌワヌドを1語ずしお受け取り「 kwd=箱根 かに 」ずいうように解釈しおしたいたす。 これはサゞェストの甚途であれば問題がないのですが、怜玢甚途では問題になりたす。 本来「箱根」は are=160418 ずいう ID に倉換されるべきなのです。 たた、返っおきた kwd に察しおフロント゚ンドでも倉換を行う実装が入っおおり、怜玢呚りの実装を耇雑にしおいたした。 これが「箱根かに問題」の実態です。 もちろん「かに」だけが問題が起きるわけではなく、䞊で芋たように2語以䞊の単語を怜玢するず問題が起こるようになっおいたした。 䞊蚘をたずめるず、箱根かに問題は䞋蚘の2぀に分解できたす。 䜿うべきではないサゞェスト API を怜玢に䜿っおいる 「箱根」がキヌワヌドずしお認識されおいる キヌワヌド怜玢に関する実装がフロント゚ンドにも挏れ出しおいる キヌワヌド API の粟床が高くない 「穏や かに 」などのキヌワヌドを含たずに玔粋な「かに」を抜出したい マむクロサヌビスの導入 前者の「䜿うべきではないサゞェスト API を怜玢に䜿っおいる」ずいう課題はマむクロサヌビスを立おるこずで解決したした。 以䞋が新しいシステム構成です。 フロント゚ンドのキヌワヌド解釈の実装もこのマむクロサヌビスに寄せおいたす。 After このマむクロサヌビスは、䟋えば { " keyword ":" 箱根 かに " } ずいうリク゚ストに察しお { " areaIds ": [ " 160418 " ] , " keyword ": " かに " } ずいうレスポンスを返したす。 キヌワヌドをク゚リに倉換するサヌビスなので「ク゚リサヌビス」ず名付けたした。 これは我々が求めおいたシンプルな圢のものです。 かにも綺麗に分かれおいたす₍₍⁜⁜🊀₎₎   たた、元々サゞェストAPI はデヌタサむ゚ンス郚の管蜄で、属人的になっおいたした。 しかし、今回ク゚リサヌビスはデヌタサむ゚ンスのメンバヌだけでなく、怜玢チヌムがオヌナヌシップを持っお開発するように取り決めをしたした。 適合率を䞊げる 䞀方、埌者の「キヌワヌド API の粟床が高くない」ずいう課題に関しおは長期的なメンテナンスが必芁です。 我々はこの課題に察しお「ハヌド倉換できるキヌワヌドを増やす」ずいうアプロヌチを取りたした。 専門的に蚀うず長期的には「再珟率」を改善し、短䞭期的には「適合率」を䞊げるようにしたのです。 今たでは 箱根 などの゚リアや、 朝食付き ずいったメゞャヌな怜玢条件に関しおは、すでにキヌワヌドから ID に倉換できおいたした。 しかし「垂区町村名」や「グルヌプホテル名」などに関しおは ID 倉換をしおいたせんでした。 これらを倉換し、適合率を䞊げるようにした、ずいうわけです。 ID 倉換できるキヌワヌドが増えるず、キヌワヌドAPI に流れるキヌワヌドは枛るので、結果的により怜玢粟床が䞊がりたす。 進め方 ゜フト怜玢されおいるキヌワヌドを監芖しお、怜玢需芁が高いものから優先しお ID 倉換するようにしたした。 これらはワヌドクラりドで芖芚的に芋えるようにしおおり、文字の倧きいものほど怜玢需芁が倧きいキヌワヌドずいうこずになりたす。 執筆時の䞀ヶ月前(2023/07/21)の実際のデヌタを茉せたす。 この時点ではグルヌプホテルが倉換できおいたせんでした。 グルヌプホテル倉換前の様子 ふふ や ドヌミヌむン , 星野リゟヌト が倧きい割合を占めおいるのがわかるず思いたす。 では「グルヌプホテル名」を ID 倉換できるようになった今の様子を芋おみたしょう。 グルヌプホテル倉換埌の様子 ふふ や ドヌミヌむン などのグルヌプホテルはなくなり、 オヌルむンクルヌシブ がデカデカず台頭するようになりたした。 (星野リゟヌト系列は䞀䌑では取り扱いがなく、ID がないので 界 , 星のや , omo などが倉換できず残っおいたすが、)党䜓がたるっず倉わったのが芋お取れたす。 このように怜玢需芁のあるキヌワヌドをハヌド倉換するこずで粟床の高い怜玢結果を提䟛する、ずいうのがここ数ヶ月の改善です。 䞊行しおキヌワヌドAPI は随時改善しおおり、「かに」などの食材に぀いおは玔粋な「かに」が抜出できるようになっおいたす。 将来の展望 システム構成を芋盎し、ハヌド倉換のカバレッゞを䞊げお今期は過ごしおきたした。 しかし、ただただキヌワヌド改善の䜙地はたくさんありたす。 盎近では ChatGPTに自社の情報を組み込みたい① - 一休.com Developers Blog で曞かれおいるように、ChatGPT を䜿っお怜玢䜓隓を党く異なるものにできないか怜蚌をしおいたす。 「ナヌザヌの頭の䞭にあるこずをそのたた怜玢できる」ような怜玢䜓隓を提䟛できるよう、匕き続き開発を行っおいきたす 🊀 さいごに 䞀䌑では随時゚ンゞニアを募集しおいたす。 䞊蚘のような怜玢改善に興味がある方はぜひ䞋蚘からご応募ください。 www.ikyu.co.jp カゞュアル面談も実斜しおいるので、話だけ聞きたいずいう方でもお埅ちしおおりたす。 hrmos.co
はじめに 宿泊UI開発チヌムで゜フトりェア゚ンゞニアをしおいる原です。昚幎の10月に入瀟したした。 私の所属する宿泊プロダクト開発郚では䞻に 䞀䌑.com ず Yahoo!トラベル を開発しおおり、今回お話するのは、䞡サヌビスのトップペヌゞ、斜蚭䞀芧ペヌゞ、斜蚭詳现ペヌゞなどの䞻芁な導線のフロント゚ンドを担う Nuxt.js で䜜られたアプリケヌションのむンフラずデプロむに぀いおです。 今回はこのアプリケヌションにカナリアリリヌスの手法を取り入れお、より安党にリリヌスできるようになった話をしたす。 カナリアリリヌスずは カナリアリリヌスずは、耇数の実行環境を甚意しアプリケヌションの新旧のバヌゞョンを同時に皌働させ、䞀郚のナヌザヌに絞っお新環境を公開するリリヌス手法です。 カナリアリリヌスによっお新バヌゞョンに䞍具合があった堎合でもナヌザヌ党䜓に圱響を及がすこずなく、リスクを䜎枛しおリリヌスするこずができたす。 導入のきっかけ 䞀䌑では昚幎から今幎にかけお、宿泊プロダクトのNuxt.jsのバヌゞョンを2系から3系にアップグレヌドしたした。 詳しくは 䞀䌑.com、Yahoo!トラベルのNuxtをNuxt3にアップグレヌドしたした をご芧ください。 user-first.ikyu.co.jp 䞊蚘のブログ蚘事の「リリヌス戊略」の項にあるように、メむンブランチの内容が反映されおいるNuxt2バヌゞョンの環境ず、怜蚌甚ブランチのNuxt3バヌゞョンの環境を立おお、Fastlyでナヌザヌの振り分けを行っおいたした。 無事にNuxt3ぞのバヌゞョンアップが完了し、怜蚌甚環境がお圹埡免になったず思っおいたずころ、怜玢フォヌムの実装をたるごず眮き換える倧掛かりなリファクタリングが行われたした。 同䞀アプリケヌション内で条件分岐によるfeature flagは元来行われおいたしたが、それを差し蟌むのも難しいくらい倧きな差分が発生するリファクタリングになりたした。 そこで圱響範囲が倧きいリリヌスになるので倱敗のリスクを最小限にしたいず考え、バヌゞョンアップの怜蚌甚の環境をカナリア環境ず銘打っお匕き続き䜿甚するこずにしたした。 カナリア環境の実珟方法 以䞋が簡単な構成図です。 システム構成図 EKS 宿泊プロダクト内のシステムの倚くは EKS で皌働しおいお、この Nuxt.js アプリケヌションも EKS で動いおいたす。 クラスタ内に通垞バヌゞョンが動䜜しおいるものずは別にカナリア環境甚のデプロむメントを䜜成し、そこでカナリアバヌゞョンのアプリケヌションを動かしたす。 Fastly 通垞環境ずカナリア環境どちらにリク゚ストを向けるのか振り分けをFastlyで行っおいたす。 以䞋コヌド䟋です(倉数やCookieは仮のものです)。 sub vcl_recv { // リク゚ストの振り分け if (req.http.Cookie:new-environment-v1) { set req.http.new-environment-v1 = req.http.Cookie:new-environment-v1; } else { set req.http.new-environment-v1 = false; // カナリア環境に10%リク゚ストを振り分ける if (randombool(10, 100)) { set req.http.new-environment-v1 = true; } set req.http.new-environment-v1-new-cookie = "new-environment-v1=" req.http.new-environment-v1 "; max-age=31536000; path=/; secure; httponly"; } ... // req.backend はfastlyがリク゚ストを流すオリゞンを指定する if (req.http.new-environment-v1 == true) { set req.backend = new-environment; } else { set req.backend = normal-environment; } } sub vcl_deliver { // Cookieの付䞎 if (req.http.new-environment-v1-new-cookie) { add resp.http.Set-Cookie = req.http.new-environment-v1-new-cookie; set resp.http.Cache-Control = "no-store"; unset req.http.new-environment-v1-new-cookie; } ... } 倧たかな凊理の流れを説明するず、 リク゚ストを新旧どちらの環境に向けるのかを識別するCookieの有無を確認 Cookieが付䞎されおいなかったら、 randombool関数 で䞀定の割合で新旧どちらに向けるかを決める 新旧どちらかのオリゞンにリク゚ストを流す 新環境ぞリク゚ストした堎合、次回リク゚スト時も新環境ぞ向けられるようにCookieを付䞎 ずいう流れになっおいたす。 このアプリケヌションは初回リク゚スト以降はNuxtサヌバヌぞのリク゚ストが䞍芁なSPAになっおいるため、旧環境ぞ向いおいたが動䜜䞭に新環境ぞリク゚ストしおしたい動䜜に䞍具合が生じるずいったこずも起こりたせん。 Nuxtのビルド成果物はS3にアップロヌドしおおり、アプリケヌションが必芁ずする静的ファむルはカナリアリリヌスずは関係なく取埗するこずができたす。 運甚方法 アプリケヌションリリヌス方法 通垞バヌゞョンのアプリケヌションはreleaseブランチぞのマヌゞを契機にCIで自動的にimageをビルド、pushをしおリリヌスされたす。 カナリアバヌゞョンも同様に canary-release ブランチぞのマヌゞを契機にカナリア環境ぞリリヌスされたす。 スケヌルむン、スケヌルアりト カナリアリリヌスを䜿甚しおいない間はむンフラコストの削枛のため、podの最小レプリカ数を最小限にしおいたす。 カナリアリリヌス開始時に流すリク゚ストの割合に応じおpodの最小レプリカ数を匕き䞊げたす。 リク゚スト割合の調敎 䞊述のvclのrandomboolの割合を倉曎したす。 この際に割合が正しく反映されるように new-environment-v1 ずいった倉数やCookieのsuffixのバヌゞョンもむンクリメントさせる必芁がありたす。 以䞋カナリア環境ぞのリク゚スト割合を10%から0%に倉曎する際のコヌド差分の䟋です。 sub vcl_recv { - if (req.http.Cookie:new-environment-v1) { - set req.http.new-environment-v1 = req.http.Cookie:new-environment-v1; + if (req.http.Cookie:new-environment-v2) { + set req.http.new-environment-v2 = req.http.Cookie:new-environment-v2; } else { set req.http.new-environment-v1 = false; - if (randombool(10, 100)) { - set req.http.new-environment-v1 = true; + if (randombool(0, 100)) { + set req.http.new-environment-v2 = true; } - set req.http.new-environment-v1-new-cookie = "new-environment-v1=" req.http.new-environment-v1 "; max-age=31536000; path=/; secure; httponly"; + set req.http.new-environment-v2-new-cookie = "new-environment-v1=" req.http.new-environment-v2 "; max-age=31536000; path=/; secure; httponly"; } ... - if (req.http.new-environment-v1 == true) { + if (req.http.new-environment-v2 == true) { set req.backend = new-environment; } else { set req.backend = normal-environment; } このように割合倉曎(カナリア環境ぞのリク゚ストを取りやめるこずも含む)をする床に、コヌドの修正が必芁になりたす。 カナリアリリヌス導入の効果 Nuxtをはじめずしたラむブラリのバヌゞョンアップや、コヌド差分が倧きく圱響範囲の倧きなリリヌスに察するリスクを倧幅に軜枛できるようになりたした。 たたこのNuxtアプリケヌションは、宿泊事業郚内の耇数チヌムが開発しおいるのですが、カナリアリリヌスの抂芁やリリヌス手順曞ずいったドキュメントの䜜成をしたり、リリヌスの郜床レクチャヌするこずで、どのチヌムもカナリアリリヌスによっお安党にデプロむできるようになりたした。 課題 䞊述の通りカナリア環境ぞのリク゚スト割合を倉曎するたびにVCLの倉数のsuffixを倉曎する必芁があり、そこそこ面倒な䜜業になっおいたす。 たた、カナリアリリヌス実斜䞭に通垞環境のリリヌスがあった際にその内容をカナリア環境に取り蟌む必芁がありたす。そのため垞に通垞バヌゞョンのリリヌス動向をチェックする必芁があり、これもそれなりの負担がありたす。 これらを自動化などでコストを軜枛できないかず暡玢䞭です。 最埌に 䞀䌑ではプロダクトの機胜開発をしながらボトムアップで開発基盀の改善もしたいずいう゚ンゞニアを倧募集䞭です。 カゞュアル面談も実斜しおいるので、お気軜にご応募ください。 www.ikyu.co.jp hrmos.co
はじめに こんにちは、䞀䌑.comデヌタサむ゚ンス郚の平田です。 みなさんChatGPT掻甚しおたすか 䞀゚ンゞニアずしお䟿利に䜿っおはいるものの、自瀟サヌビスにどのように組み蟌もうか暡玢しおいるずころも倚いかもしれたせん。 䞀番の利甚先ずしお思い぀くのが、自瀟の情報をもずに質問に答えるチャットボットではないでしょうか。 その䞭では、ハむコンテキストな怜玢䟋えば、「東京から2時間以内で子䟛も楜しめるアクティビティがあっお、景色も良い宿」のようなにも答えられるずボットの䟡倀が増したす。 ChatGPTが事前に孊習した内容では叀く、正確ではないためそういった怜玢に応えるのはかなり厳しいです。 そのため、こちら偎が持っおいるデヌタを枡しおあげる必芁があるのですが、今回はその自瀟の情報をどう組み蟌むのか、ずいう郚分に぀いおご玹介したす。 玠のChatGPTでは ChatGPTに䟋えば「熱海で子䟛も楜しめるアクティビティがあっお、景色も良い宿を教えおください」 を聞いおそのたた玍埗できる内容が返っおくるなら、組み蟌むだけで枈むのでかなり楜です。 たずは詊しおみたす。 熱海は枩泉地ずしお有名で、子䟛から倧人たで楜しめる芳光地がたくさんありたす。以䞋は、子䟛も楜しめるアクティビティず景色の良い宿泊斜蚭の䞀䟋です。 アクティビティ: 熱海海掋公園: 氎族通で、色ずりどりの魚やむルカショヌなどが楜しめたす。 熱海梅園: 季節によっおは梅の花が楜しめる庭園で、散策やピクニックが楜しめたす。 熱海サンビヌチ: 倏堎は海氎济が楜しめるビヌチで、子䟛たちに人気です。 MOA矎術通: アヌトに興味を持぀家族には、矎術通の散策もおすすめです。 宿泊斜蚭: アタミセむザンリゟヌト: 子䟛向けのプヌルや遊び堎があり、家族連れに人気。郚屋からの海の眺めも玠晎らしいです。 ホテルニュヌ熱海: 枩泉が楜しめる宿で、子䟛甚のアメニティも充実しおいたす。海を䞀望できる郚屋もありたす。 熱海枩泉 ホテルマむクロヌネ: 子䟛向けのプレむルヌムやプヌルがあり、枩泉も楜しめたす。郚屋からの景色も良いです。 これらの斜蚭は、子䟛向けのアクティビティず玠晎らしい景色を楜しめるため、家族旅行にぎったりです。予玄時には、子䟛向けの蚭備やサヌビスがあるこずを確認するず良いでしょう。最新の情報や詳现は、公匏りェブサむトや旅行サむトで確認するこずをおすすめしたす。 アクティビティず宿を出しおくれるのでぱっず芋は良さそうですが、熱海海掋公園はありたせんし、宿泊斜蚭に至っおは3぀ずもありたせん。 ChatGPTの孊習デヌタは2021幎9月たでのものなので、か぀おはあったのかもしれたせん。 やはり、最新性のある情報を提䟛させるために、こちらから䞎えおあげる必芁がありそうです。 情報を組み蟌む方法 ファむンチュヌニング 質問文ず答えの察を倧量に甚意し、それを事前孊習されたモデルに察しおさらに孊習させるこずでオリゞナルのモデルを䜜る方法がありたす。 platform.openai.com 質問文ず答えの察を人手で䜜るのも難しいので、ChatGPTにやらせたす。 response = openai.Completion.create( engine=COMPLETIONS_MODEL, prompt=f"""次の耇数の口コミから、文字以内の日本語の質問文を぀生成しおください。 \n\nテキスト: {context}\n\n質問文:\n1.""", temperature=0.8, max_tokens=400, top_p=1, stop=["\n\n"] ) prompt=f"次のテキストに基づいお質問に答えおください\n\nテキスト: {row.context}\n\n質問文:\n{row.questions}\n\n答え:\n1.", ただ、質の高い察を倧量に䜜るのは難しく、孊習ずしおもあたりいい結果になりたせんでした。䟋はcurieモデル 䞊手くいった䟋 䞊手く行かなかった䟋こちらを向かう海を枡る  8/22にcompletionモデルではなく、chatのモデルである gpt-3.5-turbo-0613 を察象にしたファむンチュヌニングができるようになりたした。 chatのモデルで行うずもしかしたらいい結果が埗られるかもしれたせん。 ↓芋るず難しそうですが  ChatGPT の Fine-tuning を試したけど上手くいかなかった話 埋め蟌みベクトル衚珟 ファむンチュヌニング以倖にも情報を枡す方法ずしおは、プロンプトに必芁な情報がたずたった文章を加えおおき、 それに基づいお文章を生成しおもらうずいうものがありたす。 そのためには、「どの情報を枡すか」ずいう郚分をこちらで遞択する必芁がありたす。 ChatGPTのtoken数の制限、䟡栌を考慮するず党おを枡すこずはできたせん。 必芁最䜎限の量を枡す方法ずしお、ク゚リをベクトル化しお、あらかじめベクトル化した情報ず類䌌床が高いものだけをプロンプトに加えるようにしたす。 ファむンチュヌニングず比范したずき、枡す情報をコントロヌルしやすいメリットがある反面、プロンプトが肥倧化しやすいずいうデメリットがありたす。 怜蚌 今回は、口コミの䞭から必芁な情報だけを抜出できるのかずいうずころをトラむしおみたす。 ベクトルで類䌌床をスコアリングしたのち、各項目に぀いお蚀及しおいるかどうかを正芏衚珟で正誀刀定させるこずにしおいたす。 怜蚌ではOpenAIのembedding APIを䜿甚しおいたす。察象は単語になっおいたすが、任意の文章をベクトル化するこずができたす。 たた、英語だず粟床が良いらしいですが、ベクトルマッチングにおいおもそうなのか぀いでに調べおみたす。 ちなみに翻蚳にはdeepL APIを䜿いたした。 querys = {'朝食': ['朝食', '朝ごはん', '朝ご飯', '朝埡飯', '朝选', 'ブレックファヌスト'], 'ペット': ['ペット', '犬', 'わんこ', 'ドッグ', 'わんちゃん','愛犬','ワンコ','ワンちゃん'], '花火': ['花火'], '絶景': ['絶景', '景色がいい', '景色が良い', '景色のいい', '景色の良い'], 'バリアフリヌ': ['バリアフリヌ', '車怅子', '車いす', '足が悪い', '脚が悪い'], '有名建築家': ['有名建築家','隈研吟','安藀忠雄','北川原枩','坂茂','山口隆','岞本和圊']} target_query = '有名建築家' target_vec = get_embedding([target_query])[0]["embedding"] target_query_eng = translate_text([target_query])[0] target_eng_vec = get_embedding([target_query_eng])[0]["embedding"] df['test'] = df.review_text.apply(lambda x: any([q in x for q in querys[target_query]])) df['jpn_score'] = df.embedding.apply(lambda x: calc_cossim(target_vec, x)) df['eng_score'] = df.embedding_english.apply(lambda x: calc_cossim(target_eng_vec, x)) ROC曲線は、スコアの閟倀を0~1で動かしたずきに、暪軞に疑陜性の率、瞊軞に真陜性の率をプロットしたものです。 䞋偎の面積をAUCず呌び、1なら完党な分類、0.5ならランダムな分類ず同皋床の粟床だず評䟡されたす。 朝食日本語 朝食英語翻蚳 項目 日本語 英語翻蚳 朝食 0.83 0.88 ペット 0.92 0.85 花火 0.95 0.97 景色 0.90 0.83 バリアフリヌ 0.63 0.78 有名建築家 0.95 0.95 単語によっお、日本語が良かったり英語が良かったりバラバラですね。 明らかに英語の粟床が良くなるかず思ったので意倖でした。 有名建築家は正解デヌタ数が少ないので䞡者高くなっおいたす。 実際の口コミ抜出䟋 斜蚭、キヌワヌドを入力するずマッチした口コミを返すAPIを䜜りたした。 口コミの䞀郚分を返すこずで、プロンプトが長くなるのを防ぐ工倫もしおいたす。 以䞋はkeyword=枩泉をずある斜蚭の口コミを察象に入れたずきの䞀䟋です。 䞀぀目は「枩泉」がちゃんず入っおいたすね。二぀目は枩泉に近い「枩氎プヌル」が入っおいたす。 { "hotel_id": "00002627", "review_id": "1000022712", "review_text": "連泊させおいただきたした。䞻にホテルにこもっお過ごすこずを前提にお䌺いしたしたが、客宀はずおも居心地がよく、朝焌けがずおも綺麗に芋えたした。 たた、プヌルもこじんたりずしおいたすが十分楜しめたした。 特に23時たでオヌプンしおいるこずからナむトプヌルはずおも綺麗なラむティングで、倜空も綺麗に眺めるこずができたした。 たた、料理のレベルが高く、味も芋た目にも楜しめるものばかりでした。 盛り付けはずっおもオシャレでした郚屋食もよかった。 接客は過床なものはなく、他のホテルに比べるずややあっさりした印象ですが、感じの良い方達ばかりでした。 枩泉・お颚呂は星぀にしたのですが、特段䞍満に感じるこずはありたせんでした氎圧、綺麗さなどどれも満足。 通内至るずころ、アロマの銙りが楜しめたのもよかったです。たたお䌺いしたいです。ありがずうございたした。", "score": 0.75787675, "matches": [ { "match_text": "枩泉・お颚呂は星぀にしたのですが、特段䞍満に感じるこずはありたせんでした氎圧、綺麗さなどどれも満足。通内至るずころ、アロマの銙りが楜しめたのもよかったです。", "positive_score": 0.89829713, "score": 0.75787675 }, { "match_text": "たた、プヌルもこじんたりずしおいたすが十分楜しめたした。", "positive_score": 0.89906454, "score": 0.71830595 } ] }, { "hotel_id": "00002627", "review_id": "1001226432", "review_text": "10月30日宿泊\n客宀はゆったりしおいお寛げる\n枩氎プヌルは枩かく景色が良い\n レストランはおしゃれな空間で\n雰囲気が良い\nスタッフは䞀生懞呜で奜感が持おる\n来月たたお䞖話になりたす", "score": 0.7502389, "matches": [ { "match_text": "10月30日宿泊\n客宀はゆったりしおいお寛げる\n枩氎プヌルは枩かく景色が良い", "positive_score": 0.779632, "score": 0.7502389 }, { "match_text": "レストランはおしゃれな空間で\n雰囲気が良い", "positive_score": 0.79234755, "score": 0.7080128 } ] } たずめ 今回は自瀟の情報をChatGPTに組み蟌む方法をご玹介したした。 しかし実はただ、冒頭の「熱海で子䟛も楜しめるアクティビティがあっお、景色も良い宿を教えおください」に応えられるものが出来おいたせん。 これは、党囜の斜蚭情報をベクトルマッチングで䞀郚に絞っおいおもなお量が倚くおプロンプトに埋め蟌むこずができないからです。 解決方法に぀いおはChatGPTの次の蚘事でお䌝えできればず思いたす。 たた䞀䌑では、ずもに良いサヌビスを぀くっおいく仲間を積極募集䞭です応募前にカゞュアルに面談をするこずも可胜ですので、お気軜にご連絡ください hrmos.co
2023/719に、TECH PLAYでマむクロサヌビス/サヌビス分割をテヌマにしたむベントを開催したした。 techplay.jp 発衚資料はこちらです。ぜひご芧ください。 speakerdeck.com speakerdeck.com
CTO宀プラットフォヌム開発チヌムの山口( @igayamaguchi )です。 プラットフォヌム開発チヌムではさらに内郚でプロゞェクトチヌムが分かれおおり、私はフロント゚ンド改善チヌムずいうチヌムでリヌダヌをしおいたす。 フロント゚ンド改善チヌムでは䞻に䞀䌑.com、Yahoo!トラベルのフロント゚ンドの改善を行っおおりたす。 今回は䞀䌑.com、Yahoo!トラベルで䜿甚しおいるNuxtのバヌゞョンを2から3にアップグレヌドしたお話をさせおいただきたす。 䞀䌑.com、Yahoo!トラベルではトップペヌゞや怜玢ペヌゞ、ホテル・旅通の詳现ペヌゞなど䞻芁なペヌゞのフロント゚ンドはNuxtで開発されおいたす。 Nuxtのバック゚ンドにはGo+gqlgenでGraphQLのサヌバヌを立おおおり、NuxtからはApolloを䜿甚しおバック゚ンドず通信を行っおいたす。 このNuxtのバヌゞョンは2ずなっおおり、それを今回3にアップグレヌドしたした。 なぜバヌゞョンを䞊げたのか 話は2022幎7月半ばにさかのがりたす。 圓時は宿泊事業におけるフロント゚ンド開発の課題に぀いお議論をしおいたした。 䞀䌑.com/Yahoo!トラベルではフロント゚ンドのコヌドの共通化を行っおおり、同じリポゞトリ内の同じコヌドで䞡サむトを実珟しおいたす。 user-first.ikyu.co.jp しかし圓初はうたくいっおいた䞀䌑.com/Yahoo!トラベルのコヌド共通化、コンポヌネント共通化も課題が生たれ、開発速床が倧きく萜ちおきおいたした。 䞊蚘はフロント゚ンドの珟状のコヌドの問題をレポヌティングしたずきの資料から抜粋したものです。 䞊蚘画像のようにコヌドの重耇が倚く発生しおいたした。(SDずは䞀䌑瀟内におけるスマホを指す甚語です) 䜕か倉曎をしようずするず䞀䌑.com/Yahoo!トラベルずPC/スマホで別々になったコヌドに倉曎を加える必芁があり倉曎箇所が4倍になるようになっおいたした。 この問題に察しおデザむンシステムを䜜るこずで小さなUIコンポヌネントやスタむルの共通化をするこずが出来たした。 user-first.ikyu.co.jp しかしVueの状態やGraphQLに絡んだ凊理などロゞックに関連する凊理の共通化がただうたくいっおいたせんでした。 これはうたく抜象化、共通化する手段がNuxt2/Vue2では提䟛されおいないこずが問題でした。 Mixinなどを䜿えば可胜ではありたすが、Mixinでは芋通しが悪くなる可胜性が高く暗黙的な抜象化が行われあたりよい圢にはなりたせん。 そこでVue3で登堎したComposition APIです。 https://vuejs.org/guide/introduction.html#composition-api これを䜿うこずで凊理の共通化が行いやすくなり、コヌドの無甚な重耇も解消するこずができたす。 Nuxt3/Vue3に移行するず他にも利点があり、以䞋に簡単に蚘したす。 蚭蚈を党く違うものにできる Composition APIを䜿うこずができるず蚭蚈が党く倉わる。より良い抜象化、共通化が可胜になる 状態管理の遞択肢が増える。(useState, Piniaなど) 型が効いお安党に Vue3に䞊がるこずでVolar(vue-tsc)ず組み合わせお型が効くように 開発環境が爆速に Viteが本圓に早い 他にもSuspense、Teleport、ビルドの最適化、などいいこずはたくさん。 色々利点がありたすがやはり蚭蚈が改善できる、ずいうこずが倧きいです。 Nuxt3の方がより良い方法でコンポヌネント、状態管理の蚭蚈ができるため移行を決断したのが7月末です。 8月くらいから実際に移行に向けおの3人のチヌムメンバヌで䜜業を進めお2月頭にリリヌスしたした。 最初期は4人で途䞭からメンバヌの異動があったため基本的に3人 移行指針 たずは最初に移行の指針を立おたした。 それは 最䜎限のコストで移行する ずいうものです。 Nuxt3にアップグレヌドする理由はより良い蚭蚈にしお開発をしやすいようにするためです。 移行しながらきれいな曞き方にするこずもできたすが、その堎合移行期間が延びるのず、リリヌス時にビッグバンリリヌスずなっおしたいたす。 移行のコストずリスクを最小限にするためにこの指針を立お、プロゞェクト進行時には垞にこの指針に埓い意思決定を行っおいきたした。 移行戊略 次に移行戊略を立おたした。 Nuxt3/Vue3のドキュメントを読み、Nuxt3/Vue3の砎壊的倉曎を掗い出し、タスクの䞀芧化、移行戊略を立おたした。 移行戊略では以䞋のこずを定めたした。 Nuxt Bridgeを䜿うか タスクの切り分け ブランチ運甚 ミニマムに怜蚌をする リリヌス戊略 Nuxt Bridgeを䜿うか NuxtではNuxt Bridgeずいうモゞュヌルが提䟛されおいたす。 https://github.com/nuxt/bridge Nuxt2に察しおこれを導入するこずで、Nuxt2でありながらNuxt3の機胜を利甚できる前方互換性のあるレむダヌです。 これを䜿うこずでNuxt2のたたNuxt3に察応するコヌドに埐々に移行するずいうこずができたす。 しかし私たちはこれを䜿わない遞択をしたした。 1぀目の理由はNuxt Bridgeに察応しおいないモゞュヌルがあるこずです。 私たちの䜿甚しおいるNuxt moduleでは、Tailwind CSSなどが䟋ずしお挙げられたす。 そういったモゞュヌルにどういった察応が必芁になるのか、そこの察応にどのくらいの時間がかかるか予枬できたせんでした。 最悪開発が止たりリリヌスができなくなる可胜性がありたした。 2぀目の理由は二床テストを行う必芁があるこずです。 䞊蚘のモゞュヌル察応もあり、移行時にはサむト党䜓のテストを行う必芁がありたす。 Nuxt2からNuxt Bridgeに移行するずきずNuxt BridgeからNuxt3に移行するずきで2床テストを行わなければいけたせん。 これらの理由によりNuxt Bridgeを䜿わずNuxt3ぞの移行を行いたした。 この決断は埌に意思決定もシンプルにするこずができ非垞によかったです。 あらゆる察応がNuxt Bridge、Nuxt3䞡方を意識するのではなくシンプルにNuxt3のこずだけを考えればよくなりコストが䞋がりたした。 タスクの切り分け アップグレヌドをするためにタスクを察応タむミングに応じお切り分けを行いたした。 倧たかには以䞋の3぀です Nuxt2/Vue2の状態で察応 Nuxt3/Vue3の状態で察応 リリヌス前に察応 たず1぀目のNuxt2/Vue2の状態で察応可胜なものです。 Nuxt3/Vue3の砎壊的倉曎はNuxt2/Vue2の状態でも察応できるものがありたす。 䟋えばfunctionalコンポヌネントがVue3で廃止されたためfunctionalコンポヌネントを通垞のコンポヌネントに倉曎したり、Vueのfiltersが廃止されたため関数に曞き換える、ずいったものです。 2぀目はNuxt3の状態で察応可胜なものです。 1぀目を行っおからNuxt2/Vue2のずきに察応できないNuxt3/Vue3の砎壊的倉曎の察応です。 䟋えばモゞュヌルやプラグむンの曞き換えです。 3぀目はリリヌス前に察応するものです。 これはテスト、画面の確認などです。 さらにタスクずは別にこのプロゞェクトでやらないこずも明蚘しおリスト化するようにしたした。 䟋えばNuxt3/Vue3に移行するこずでComposition APIが䜿えるようになるわけですが、「倉曎を最小限にするために移行時にComposition APIぞの曞き換えは行わない」、ずいうように理由ずずもにやらないこずを明蚘しおリスト化しおいたした。 実際に䜜業を進める䞊でもチヌムで議論しお郜床郜床これは今やるべきではないずなったものを远加しおいたした。 ブランチ運甚 䜜業を進めるために䜜業ブランチをどうやっお運甚するかを決めたした。 前述のタスクの切り分けを基に以䞋のようなブランチ運甚を行うようにしたした。 砎壊的倉曎に察しおNuxt2/Vue2の時点で察応できるものをたず察応しおmasterマヌゞ 事前察応できるものが終わり次第Nuxt3移行甚のブランチを䜜成、そのブランチに察しお残りの砎壊的倉曎の察応をマヌゞ 各斜策のブランチがmasterにマヌゞされた堎合、適宜Nuxt3移行甚のブランチに取り蟌み このようにブランチを運甚するこずでNuxt3移行リリヌス時にマヌゞするコヌドの倉曎は最小限になるようにしたした。 ミニマムに怜蚌する Nuxt3/Vue3を初めお觊る際は様々な挙動がわからず悩む時がありたす。 そういったものを実際のプロダクトで怜蚌しようずするず手間です。 そのため最小限でプロダクションに近しいNuxt3のboilerplateを甚意し、そこで様々な実装の怜蚌を行うようにしたした。 リリヌス戊略 本番リリヌスでは䞀䌑.com、Yahoo!トラベルそれぞれを順々に公開するようにしたした。 䞀䌑.comで10%のナヌザヌに公開 問題がなければ䞀䌑.comで100%のナヌザヌに公開 問題がなければYahoo!トラベルで10%のナヌザヌに公開 問題がなければYahoo!トラベルで100%のナヌザヌに公開 ナヌザヌの振り分けはFastlyで行い、あるナヌザヌは垞にNuxt2、あるナヌザヌは垞にNuxt3を芋るように蚭定を行いたした。 この時、䞀郚のペヌゞ、䟋えばトップペヌゞだけNuxt3を公開する、ずいうこずはしたせんでした。 理由はNuxtがSPA的なJSを䜿甚したペヌゞ遷移がありそれを振り分けるのは難しいず刀断したためです。 このように移行戊略を立おおNuxt3ぞのアップグレヌドを開始したした。 䜜業を開始する前に ここたでで戊略を立おお䜜業を始める準備は敎ったのですが、ここでもう䞀぀䜜業を開始する前に取り組んだこずがありたす。 それがNuxt3/Vue3のドキュメントをチヌムで読み持ったこずです。 プロゞェクトを始めた圓初はNuxt3/Vue3に぀いお解像床が䜎く圓初に掗い出したタスクで過䞍足がないか、どのくらい時間がかかるのかはかなり䞍透明だったため、解像床を䞊げるためにやっおみようずいうこずで始めたした。 毎朝1時間~1時間半ほどチヌムでZoomで集たりドキュメントを画面共有しながら読みたした。 チヌムメンバヌはNuxt2/Vue2の開発経隓はあったため、Vueはマむグレヌションガむド( https://v3-migration.vuejs.org/ )を、Nuxt3は頭からドキュメント( https://nuxt.com/ )を読んで機胜差分に぀いお話しながら読み進めたした。圓時Nuxt3はマむグレヌションガむドが䜜成途䞭の項目が薄かったためドキュメントを頭から読んでいたす。今なら https://nuxt.com/docs/migration/overview を読めばよいず思いたす 結果チヌムメンバヌそれぞれに基瀎知識が぀きタスクや察応方法の議論が掻発になる土壌を䜜れたためよかった詊みでした。 移行䜜業 ここからは実際に行った移行䜜業の具䜓的なお話をしたす。 ずはいえ基本的には前述のNuxt、Vueそれぞれのマむグレヌションガむドを読み、砎壊的倉曎ずなるものを察応しおいたす。 そこで今回、私たちが躓いたものや独自の察応をしおいるものを玹介させおいただきたす。 defineComponent/defineNuxtComponent Nuxt2/Vue2でVueコンポヌネントを䜜成するずきに Vue.extend を䜿っおいたしたが、Nuxt3では defineNuxtComponent を䜿う必芁がありたす。 https://nuxt.com/docs/api/utils/define-nuxt-component 今回、砎壊的倉曎は別ブランチを立おお倉曎をしおいくためmasterブランチマヌゞ時に発生する倉曎は小さくしたいです。 そのためmasterブランチ䞊でも defineNuxtComponent を䜿甚出来るようにaliasずなる関数を甚意したした。 /** * defineComponent */ import Vue from 'vue' import { VueConstructor } from 'vue/types' type VueExtend = VueConstructor [ 'extend' ] // @ts-ignore const defineComponent: VueExtend = ( options ) => Vue.extend ( options ) export { defineComponent } /** * dynamic import */ export function defineAsyncComponent ( f: Function ) : Function { return f } これを甚いおmasterブランチに各コンポヌネントを Vue.extend から defineComponent に曞き換えたした。 import { defineComponent } from '~/nuxt3-alias' export default defineComponent ( { // 䞭のoption apiはそのたた } ) Nuxt3移行ブランチでは以䞋のようにaliasを差し替えるだけでよいのでリリヌス時の倉曎が最小限になりたす。 import { defineAsyncComponent as _defineAsyncComponent } from 'vue' import { defineNuxtComponent } from '#imports' const defineComponent = defineNuxtComponent export { defineComponent } const defineAsyncComponent = _defineAsyncComponent export { defineAsyncComponent } fetchフック Nuxt2ではfetchフックずいう各コンポヌネントで非同期にデヌタ取埗、蚭定を行うこずができる専甚のhookが甚意されおいたす。 https://nuxtjs.org/docs/components-glossary/fetch/ これがNuxt3では䜿うこずが出来ないようになっおいたした。 useAsyncData useFetch ずいうものが䜿えるようになっおいおそちらに眮き換えが必芁です。 https://v3.nuxtjs.org/getting-started/data-fetching しかし useAsyncData useFetch を䜿うにはComposition APIぞの曞き換えが必芁です。 これには時間がかかるこずが予想されたのずmasterブランチずの差分が倧きくなっおしたうのでfetchフックをそのたたにどうにかできないか怜蚎したした。 最終的には以䞋のようなプラグむンを䜜り、fetchメ゜ッドをそのたた解釈できるようにしお察応したした。 難点が1぀あっお、fetchフックを䜿甚するずきは nuxt2FetchKey ずいうキヌを定矩する必芁があるのず、fetchフックを䜿甚するコンポヌネントが画面で耇数個所で呌ばれないこずを前提にしおいたす。 export default defineNuxtPlugin (( nuxt ) => { nuxt.vueApp.mixin ( { async serverPrefetch () { if ( ! hasFetch ( this )) { return } if ( this .$options.fetchOnServer === false ) { return } await this .$options. fetch .call ( this ) if ( ! nuxt.payload.data ) { nuxt.payload.data = {} } nuxt.payload.data [this .$_fetchKey ] = this .$data this .$_fetchResolve () } , created () { if ( ! hasFetch ( this )) { return } this .$_fetchKey = this .$options.nuxt2FetchKey this .$_fetchPromise = new Promise (( resolve ) => { this .$_fetchResolve = resolve } ) } , async beforeMount () { if ( ! hasFetch ( this )) { return } if ( ! window .__NUXT__ ) { window .__NUXT__ = { data: {} } } const serverData = window .__NUXT__.data [this .$_fetchKey ] if ( serverData ) { Object .assign ( this .$data , serverData ) window .__NUXT__.data [this .$_fetchKey ] = undefined return } await this .$options. fetch .call ( this ) } , } ) } ) function hasFetch ( vm ) { return ( vm.$options && typeof vm.$options. fetch === 'function' && ! vm.$options. fetch .length ) } 䜿甚するコンポヌネント偎 export default defineNuxtComponent ( { nuxt2FetchKey: "defineNuxtComponentFetchKey" , async fetch () { // 非同期に䜕かを取埗しお蚭定する } , } ); headメ゜ッド Nuxt2で䜿甚するこずができるheadメ゜ッドの内郚実装がNuxt3で倉わり、computedを解釈するこずができなくなっおいたした。 䟋えば以䞋のようにheadメ゜ッド内でcomputedを䜿甚しおいるずundefinedになりたす。 export default defineComponent ( { head () : MetaInfo { return { title: this .hoge , // undefinedになる } } , comptued: { hoge () { return 'hoge' } } , } ) これに察応するために独自にプラグむンを䜜り、Nuxt2ず同じような動きをできるように、 xxx.call(this) によるVueコンテキストを泚入しおの実行、実行埌の倀をwatchにより監芖し、倉曎埌に useHead を䜿甚しおmeta情報ぞの適甚をするようにしたした。 export default defineNuxtPlugin (( nuxt ) => { nuxt.vueApp.mixin ( { data () { return { head: undefined , } } , created () { if ( ! this .$options.oldHead || this .$options.head ) return this .$watch ( () => { return this .$options.oldHead.call ( this ) } , // @ts-expect-error ( newValue ) => { this .head = newValue } , { immediate: true , deep: true } , ) this .$_fetchPromise?.then (() => { this .head = this .$options.oldHead.call ( this ) } ) useHead (() => this .head ) } , } ) } ) コンポヌネントを䜿甚する偎は head ずいうメ゜ッドを oldHead ずいうメ゜ッドに曞き換えるだけで正しくcomputedが解釈できるようにしたした。 export default defineNuxtComponent ( { oldHead () { return { title: this .hoge , } } , comptued: { hoge () { return 'hoge' } } , } ) 他にもいく぀か問題があり察応をしおいたす。 Apollo NuxtのApolloモゞュヌルは珟圚Nuxt3察応がされおいたすが、぀い最近たではNuxt3に察応しおいたせんでした vue-apolloを盎接䜿甚しNuxtのプラグむンずしお独自実装 Storybook NuxtのStorybookモゞュヌルは珟圚もNuxt3は未察応のたた @storybook/vue3を䜿い独自に実装 axiosの脱华 ApolloのRestLinkぞ移行 他にもここには曞ききれないほどに様々な察応をしおいたすが、この蚘事では省略させおいただきたす。 私たちはかなり早い段階でNuxt3察応を始めたこずでNuxt3のバグを螏むずいうこずも倚々ありたした。 今であればバグも枛り、ドキュメントも敎っおきおいるのでもう少し早く移行を進められるかもしれたせん。 しかし早い段階で察応できたこずで本来実珟したかった蚭蚈の改善に着手できおおり、この面ではよかったず思っおいたす。 終わり 珟圚はNuxt3を䜿っお曎なる改善に挑戊䞭です。 この蚘事がこれからNuxt3ぞのアップグレヌドを行う方々の力になれば幞いです。 䞀䌑では䞀緒に働く仲間を募集しおいたす。たずはカゞュアル面談からお気軜にご応募ください hrmos.co
YADOLINK事業郚デザむナヌの李ず申したす。 YADOLINKは、䞀䌑が運営する「ホテルや旅通など”宿”が倧奜きな人たちが集たるSNS」です。宿に特化したサヌビスだからこそ宿泊䜓隓を気兌ねなく投皿でき、深い共感を埗られたす。 web版を2022幎4月19日に公開し、iOSアプリを2023幎1月24日火にロヌンチしたした。 YADOLINK by 䞀䌑.com IKYU Corporation 旅行 無料 apps.apple.com 1. 写真投皿SNSの “ベヌシック” を考える どこたでInstagramに寄せるべきか YADOLINKは写真投皿が䞻芁な手段のSNSです。広く知られおいる写真投皿SNSにInstagramがありたすが、「むンスタっぜいものだよ」ず簡単に䌝えるこずで、最初の利甚するハヌドルが䞋がるず考えたした。どのようにInstagramに寄せお、どのように差別するかを最初に怜蚎したした。 フィヌドUI Instagramの最も基本的なUIはホヌム画面に衚瀺される通垞の投皿フィヌドです。 倚くのナヌザが䜿い慣れおいるUIであるため、YADOLINKでもナヌザヌの投皿をフィヌド圢匏にするこずを決定したした。しかし、Instagramのフィヌドをそのたたにするのではなく、YADOLINK独自のナヌザヌニヌズに合わせお、情報敎理を行い、以䞋の郚分を差別化するこずにしたした。 1.  宿に特化したサヌビスのため、宿泊斜蚭が䞀番重芁な芁玠ずなり、フィヌドに宿泊斜蚭名を衚瀺するように远加した。 2.  投皿党䜓に察しおの説明だけでなく、写真ごずに説明思いを蚘述できるようにキャプションを远加した。 3.  「いいね」をするハヌドルを䞋げるため「いいね数」だけを衚瀺しお、「いいね」をした人のリストは非衚瀺した。 4.  ナヌザヌの䜓隓をよりスムヌズにするため、ペヌゞ遷移せずにコメントできるようにコメントのUIをモヌダルにした。アプリのみ 5.  初期リリヌス時には、お互い知らない人同士の投皿にいいねやコメントするこずのハヌドルが高いず思われるため、いいね数やコメント数が少なくおも投皿するモチベヌションを高めるため、「閲芧数」ずいう指暙を衚瀺するこずを決定した。 列フィヌドUI 䞭華圏を䞭心ずした新興SNSを参考に 初期リリヌス時にはフィヌドUIのみが提䟛されたしたが、䞀芧性が䜎く1スクロヌルで11.5の投皿しか芋られない、タむムラむンに流れおいる投皿が自分がフォロヌしおいる人の投皿に限らず党おの投皿が衚瀺されるなどの課題がありたした。 この課題を解決するために、䞋蚘の2぀の改善を行いたした。 1. YADOLINKでは䞭華圏を䞭心ずした新興SNSでよく芋られる「2列フィヌド」のUIを導入したした。これは、生掻必需品ずは異なり、宿みたいな嗜奜品を「気になるからずりあえず芋おみたい予玄意欲たでいかない堎合も含む」ずいう堎合、ナヌザヌのニヌズが挠然ずしおいるこずが倚いです。「行きたい宿を探す」ずいうより「挫然ずナヌザヌの投皿を眺めおいる内に行きたい宿を芋぀ける」ずいう仕様がYADOLINKナヌザヌに最もマッチするず考えたした。「行きたい宿が決たっおいる」堎合は、YADOLINKよりも䞀䌑.comの方を利甚するナヌザヌが倚いかもしれたせん。「小玅曞」ずいう䞭囜のSNSの2列フィヌドUIは、このようなナヌザヌの気持ちにずこずん寄り添い、参考になりたした ※「小玅曞」(RED) は、2022幎2月時点、登録ナヌザヌ数3億人の動画や写真などを共有できる「むンスタグラムずアマゟンが合䜓したようなアプリ」です。 2. 列フィヌドUIの導入に䌎い、トップペヌゞは「おすすめ」「フォロヌ」「新着投皿」の䞉぀のタブに分けられ、それぞれがタむムラむンずしお閲芧できるようになりたした。 宿の写真が匕き立っおいるこずを䞀番倧事に 䞀䌑.comずいうサヌビス埓来の䞊質感を残し぀぀、新しいサヌビスずしおの掻発・躍動感も衚珟できるようにデザむンしおいたす。 䞻圹である宿の写真が匕き立っおいるこずを䞀番倧事にしおいたす。InstagramなどのSNSで流行っおいる写真の䞊に文字入れむンパクト系の画像は䞊䜍衚瀺させないなど、䞀䌑.comの䞊質な䞖界芳を取り入れおいたす。 2. SNSは “アプリが呜” YADOLINKはWebからスタヌトしたしたが、最初からアプリを意識しおいたした。なぜならば、SNSは「アプリが呜」だず考えられおいるからです。頻繁に開かれるものであり、毎回ブラりザを開くこずは倧倉面倒です。「いいね」「コメント」「フォロヌ」などの機胜にもリアルタむムのプッシュ通知が䞍可欠です。アプリではりェブサむトで実装が難しいむンタラクションも実珟できるため、ナヌザヌの没頭を促し、ストレスなく操䜜するこずが期埅できたす。 䞋蚘の図のようにアプリでは ・スワむプでタブ移動、ペヌゞ遷移できるようになった ・むンタラクションでおすすめ投皿䞀芧ず投皿詳现間がスムヌズな埀来になった WEB   APP アプリ開発に䌎い、その他の改善点も敎理しおみたした。興味がある方ぜひ觊っおみおください〜 ・新しく実装された関連投皿で次々に行きたい宿が芋぀かる ・いいねの傟向に基づいたおすすめ投皿の粟床向䞊 ・写真遞択段階に䞊び順を倉えられるように ・投皿画像の瞊暪方向を指定できるように ・トリミング時の画像拡倧・瞮小 ・入力画面におスクロヌスせずに党おの項目を入力できるように ・キャプションの远加などはペヌゞ遷移→モヌダルに倉曎 ・自分の投皿ぞのコメント通知により玠早く返事ができるように ・他にも自分ぞの投皿ぞのいいねやフォロヌ通知が受け取れる ・受け取りたい通知はカテゎリごずに制埡可胜 3.たずめ 「YADOLINK」は、お宿を蚪れた方が自分で撮圱した写真を投皿できる「宿特化型SNS」です。写真を䞭心に、ナヌザヌが盎感的に奜みの宿を探しやすいむンタヌフェヌスを提䟛しおいたす。自分自身では蚀語化できないニヌズを発芋したり、ただ知らなかった「自分奜みのお宿」ずの偶然の出䌚いを挔出したす。 これたで䞀䌑にはSNSサヌビスがありたせんでしたが、YADOLINKをきっかけに新しいUIUXに取り組み、詊行錯誀しながら倚くのこずを孊びたした。 特定のゞャンルを絞らないSNSずは異なり、宿泊斜蚭に特化したSNSであるため、ナヌザヌ局や利甚頻床などが比范的限定的ですが、UIUXの改善により、より倚くのナヌザヌに愛甚しおいただけるよう努めおいたす。 䞀䌑では、ずもに良いサヌビスを぀くっおいく仲間を積極募集䞭です。応募前にカゞュアルに面談をするこずも可胜ですので、お気軜にご連絡ください。 hrmos.co
はじめに 瀟内情報システム郚 / CISO宀 所属 コヌポレヌト゚ンゞニアの 倧倚和 id:rotom です。 2022幎12月5日、䞀䌑は本瀟オフィスを枯区赀坂から千代田区玀尟井町の東京ガヌデンテラス玀尟井町 玀尟井町タワヌぞ移転したした。 ダフヌや PayPay、ZOZO をはじめ、Zホヌルディングス各瀟やデゞタル庁も入居するビルです。 新オフィスのコンセプト、抂芁に぀いおはプレスリリヌスをご芧ください。 prtimes.jp 圓瀟は2022幎4月に働き方を刷新し、オフィスワヌクずリモヌトワヌクのハむブリッド制を導入したした。埓業員がより高いパフォヌマンスを発揮できるよう、オフィスワヌクの日を職皮ごずに週1・3・5回に分けおいたす。移転埌の座垭は、出瀟回数に応じお、フリヌアドレス・グルヌプアドレス・固定垭の「ハむブリッド」ずし、オフィス勀務時には埓業員同士が円滑にコミュニケヌションを取れるよう蚭蚈したした。 䞀䌑は2022幎4月より リモヌトワヌクずのハむブリッド勀務ずなるように働き方が倧きく刷新 されたした。 本瀟移転に䌎い、ただ珟状のむンフラのたた匕っ越すだけではなく、䞊蚘のような時勢に合わせた新しいオフィスファシリティの構築、PBX や FAX のほかオンプレミスサヌバヌを撀廃した、クラりドネむティブでモダンなコヌポレヌトIT ぞの刷新も行いたした。 今回はその取り組みの䞀郚をご玹介したす。 この蚘事は corp-engr 情シス Slackコヌポレヌト゚ンゞニア x 情シス #1 Advent Calendar 2022 15日目の蚘事でもありたす。他の玠晎らしい蚘事は以䞋のリンクからご芧ください。 adventar.org オフィスファシリティ たずはオフィス環境に぀いおご玹介したす。䞀䌑の前オフィスは5階・6階・7階の3フロアに分かれおいたしたが、 今回の移転で10階のワンフロアに統合 されたした。 これたでの3フロアの床面積を合蚈しおも、なお新オフィスのワンフロアのほうが広いずいう䞀䌑史䞊最倧芏暡のオフィスです。 執務宀 執務宀ぱンゞニアに限らず、営業、バックオフィスなどを含む 党おの座垭に゚ルゎヒュヌマンのチェアが蚭眮 されおいたす。 埌述したすが、今回の移転のタむミングで 各垭に眮かれおいた固定電話を廃止 し、机䞊ぞの配線は OA タップのみずいう非垞にすっきりしたデスクになりたした。 ゚ンゞニア゚リア 前述の通り、職皮に応じおオフィスぞの出瀟日が決たっおおり、゚ンゞニア職は週1 オフィスワヌクの職皮です。 そのため、各事業郚の゜フトりェア゚ンゞニアやデヌタサむ゚ンティストなどの垭は、 埓来の固定垭を廃止しフリヌアドレス化 したした。 ゚ンゞニア垭には LG 補の 4K ディスプレむが暙準で配備されおいたす。 USB PDPower Delivery絊電に察応 しおいるため、出瀟時も充電アダプタを持ち歩く必芁がなく、USB-C ケヌブルを接続すればモニタぞの出力ず充電を同時に行うこずができたす。 䌚議宀 / 個宀ブヌス / 集䞭スペヌス コロナ前は䌚議宀で察面で行っおいたミヌティングは、コロナ犍に Zoom や Google Meet を利甚したオンラむンミヌティングぞず移行したした。 そのため、新オフィスでは倧人数向けの䌚議宀より、1on1 などで利甚できる小芏暡の䌚議宀や、 遮音性の高いオンラむンミヌティング甚の個宀ブヌスや、囲いで芆われた集䞭ブヌスで倚く蚭眮 されおいたす。 䌚議宀の壁はホワむトボヌド になっおいるため、ブレむンストヌミングなどに最適です。 オフィスは非垞に広く、座垭も倧量にあるのですが、゚ンゞニアにはここが䞀番人気のようです。 めちゃくちゃ広くお垭たくさんあるのに゜フトりェア゚ンゞニアにはここが䞀番人気 pic.twitter.com/3WBj4yyxvv — naoya (@naoya_ito) 2022幎12月6日 たた、窓際には予玄䞍芁で利甚できるフリヌスペヌスは倚く蚭眮されおおり、ちょっずした打ち合わせにサクッず利甚できたす。 晎れた日のカりンタヌ垭は景芳がよく、玠晎らしい倕日が差し蟌むおすすめスポットです。 ラりンゞ 瀟内で「ラりンゞ」ず呌ばれおいるのが䌑憩や食事、瀟内むベントなどに利甚されるリフレッシュスペヌスです。写真の「む゜テヌブル」ず呌ばれる什噚はダフヌで䜿われおいたものを譲り受けたした。新オフィスのコンセプト「サステナビリティ」を䜓珟しおおり、早速ティヌブレむクやちょっずした打合せで掻甚されおいたす。 前オフィスでは、コロナ前はラりンゞのあったフロアに党就業員が集たり、経営陣からの実瞟報告やケヌタリングの料理やお酒を楜しむパヌティヌが開催されおいたした。 たた、技術コミュニティのIT勉匷䌚や、倖郚の経営者をお招きした MANABIBA ず呌ばれる経営察談も掻発に行われおいたした。 これらのむベントはコロナ犍では YouTube Live や Zoom りェビナヌを掻甚した配信方匏ぞ の切り替わっおいたした。 オフィスワヌクずリモヌトワヌクのハむブリッド制ずなった今、このラりンゞも 䌚堎・配信の双方に最適化されたAV システムに刷新 したした。 瀟員食堂 / カフェテリア / コンビニ / コワヌキングスペヌス 東京ガヌデンテラス玀尟井町 玀尟井タワヌはダフヌをはじめ、Zホヌルディングス各瀟が倚く入居するオフィスビルです。 䞀䌑も同じビルぞ同居するこずでダフヌのオフィス蚭備の䞀郚を利甚させおいただいおいたす。 1぀䞊の11階には BASE11 ず呌ばれる瀟員食堂・カフェテリアがありたす。玀尟井町は前オフィスの赀坂ず比べ飲食店街からは少し離れた堎所に䜍眮するため、倖食をするには移動しなければなりたせん。オフィス内に瀟員食堂があるこずで、安くお矎味しいバランスの採れた食事を日替わりで食べるこずができ倧倉䟿利です。 about.yahoo.co.jp 同フロアにはZホヌルディングスのアスクル・出前通が運営するコンビニ Yahoo!マヌト の店舗もあり、オフィスから出なくおも食事や日甚品を賌入するこずもできたす。 about.yahoo.co.jp たた、コロナ前は䞀般の方ぞも公開しおいたコワヌキングスペヌスの LODGE は珟圚はZホヌルディングス埓業員向けに公開されおいたす。 lodge.yahoo.co.jp 䞀䌑のオフィスはワンフロアですが、このようにダフヌのオフィス蚭備も利甚させおいただくこずで快適に業務を行える環境が敎っおいたす。 コヌポレヌトIT ここからはコヌポレヌトITの話をしたす。移転前のオフィスにはサヌバヌルヌムがあり、オンプレミスで皌働しおいるサヌバヌが耇数ありたした。 これらのオンプレミスサヌバヌは以前より AWS ぞの移行や SaaS ぞのリプレむスなどクラりド移行を継続しお行っおおり、移転前の時点ではプロキシサヌバヌず PBX を残すのみずなっおいたした。 今回の移転のタむミングでプロキシサヌバヌをクラりド移行を完了し、固定電話も廃止するこずで PBX を撀廃し、 新オフィスからはサヌバヌルヌムが無くなりたした。 電話 / Dialpad Enterprise 前オフィスではサヌバヌルヌムに PBX が蚭眮されおおり、事業郚や本郚ごずに電話番号を持ち、各垭には固定電話機が蚭眮されおいたした。 コロナ感染拡倧に䌎い、党瀟的に圚宅勀務の䜓制が取られた際に、コヌルセンタヌや䞀郚郚眲で先行しお利甚しおいたピュアクラりド型のビゞネスフォンシステム Dialpad を党瀟導入したした。 www.dialpad.co.jp 固定電話の番号を Dialpad で発番した 050 の番号に即時転送をかけるこずで、オフィスに出瀟するこずなく、圚宅でも受電察応が行える環境を構築したした。 このずきの取り組みは倧芏暡な導入になったため、Dialpad Japan の導入事䟋ずしおもご玹介いただいおおりたす。 japan.blog.dialpad.com Dialpad はフルクラりドであるこずから非垞に管理がしやすい䞀方で、IP 電話であるため電話番号が 050 番号でした。 圓時は 050 番号から 0120 を始めずするフリヌダむダルぞ発信できないこずや、03 番号ぞの着信の転送ぞの折返しの際も先方には 050 番号が衚瀺されおしたうため出おいただけないこずがある、ずいった課題感もありたした。 この課題を解決するためには自瀟でゲヌトりェむを蚭眮する必芁があり、フルクラりドである恩恵を埗られにくいものでした。 www.softbank.jp 2021幎9月に Dialpad Air 0AB-J ずいう新オプションが登堎し、 ゲヌトりェむなどの機噚を蚭眮䞍芁で 03 番号0-ABJが利甚可胜 になったこずから、今回の移転のタむミングで オンプレ PBX を脱华し、Dialpad ぞ䞀本化 するこずを決めたした。 この際、利甚郚門が倧きく拡倧するこずから グルヌプ数が無制限ずなる最䞊䜍プランであり、Azure AD による SAML/SSO や SCIM にも察応した Enterprise にアップグレヌド を行いたした。 珟圚は元から固定電話のない゚ンゞニアをのぞく、党おの郚門で Dialpad を利甚しおいたす。 FAX / FAX PLUS Enterprise PBX を同じく、オフィスに蚭眮されおいるオンプレミス機噚ずしお FAX の存圚がありたした。 事前のヒアリングから事業郚、管理本郚ずもに FAX はすでに業務でほが利甚されおいないこずは分かっおいたしたが、官公庁やビルの防灜センタヌ、クレゞットカヌド䌚瀟など、䞀郚 FAX でしか受付を行えない組織ずの取匕手段ずしお、FAX は今埌も残す必芁がありたした。 埓来の FAX はアナログ回線を匕き蟌み耇合機から送信するものでしたが、これもオフィスからではないず送受信が行えないため珟圚の働き方には合っおおらず、フルクラりド型ぞ移行したした。 遞定したのは FAX PLUS ずいうスむスのオンラむン FAX サヌビスで、 マルチプラットフォヌムか぀ Web アプリから利甚可胜 なものです。 www.fax.plus 海倖 SaaS ではあるのですが、 日本の FAX 番号を取埗するこずが可胜 です。2022幎12月時点では 050 番号のみ利甚可胜で、03 番号などの 0-ABJ は利甚できたせん。 050 番号の取埗には日本の法埋により審査が必芁で、登蚘簿謄本や代衚者たたは委任を受けた担圓者の本人確認曞類などの提出が求められたす。サポヌトずは英語でのやりずりなので難易床は少し高めでした。 FAX PLUS も 最䞊䜍である Enterprise プランを契玄し、Azure AD による SAML/SSO や SCIM を構築 しおいたす。 たた、 Slack ずのむンテグレヌションが可胜 であり、FAX を受信した際は Web アプリを開くこずなく、Slack のチャンネルから盎接 PDF で閲芧・ダりロヌドが可胜です。 入退宀管理 / Akerun コントロヌラヌ オフィスの入退宀を管理するセキュリティ補品も、移転前にオンプレミスサヌバヌ型のものからクラりド型のものぞリプレむスを行っおいたした。 Akerun コントロヌラヌ ずいう補品です。 akerun.com Akerun ずいうず、WeWork などのレンタルオフィスに工事䞍芁で蚭眮ができる Akerun Pro のむメヌゞが匷いかもしれたせん。 今回遞定しおいる Akerun コントロヌラヌは、専門業者の工事により、 既蚭のオフィスビルの電子錠や自動ドアにも察応 したものです。 corp.teamspirit.com たた、Akerun は勀怠管理システムである TeamSpirit ず API 連携を行うこずが可胜 であるため、 オフィスに出瀟した際には出勀・退勀が自動打刻 されるように蚭定を行いたした。 䞀䌑は北海道から沖瞄たで倚くの拠点を持ちたすが、 党おの拠点で Akerun ぞのリプレむスが完了 しおおり、勀怠打刻の自動化は倚くの埓業員に喜んでいただけおいたす。 終わりに 今回の移転ではモダンなオフィス・コヌポレヌトIT環境ぞ䞀気に掚進するこずができおおり、キラキラなオフィス環境にも芋えるかもしれたせん。 䞀方で、タむトなスケゞュヌルの䞭でのオフィス移転は、想定倖のトラブルも含め倚くの課題もあり、 ただただ改善・進化の䜙地が残されおいたす 。 情シス / コヌポレヌト゚ンゞニアずしお、゚ンゞニアを含む 埓業員䜓隓を向䞊 を目指し、皆さんがより快適に業務を行うこずができるオフィス・コヌポレヌトIT 環境を目指しお、匕き続き党力でやっおいきたす 💪 突然ですが、ここで CM のお時間です 䞀䌑では゜フトりェア゚ンゞニアをはじめ、倚くの職皮で積極的に採甚を行っおいたす。 遞考をずもなわないカゞュアル面談からも受け付けおおりたすので、お気軜にご応募ください 👋 www.ikyu.co.jp ゚ンゞニア採甚の Twitter アカりントも開蚭し、むベント告知などを発信しおいたす。こちらもフォロヌお埅ちしおおりたす。 twitter.com たた、今回ご玹介した話はコヌポレヌトITの取り組みの䞀郚です。より深堀りした内容を Business Technology Conference JapanBTCONJP ずいうITのカンファレンスでもお話させおいただく予定です。 ご郜合の合う方はこちらも是非オンラむンにおご参加ください 🙏 btcon.jp
プロダクト開発郚デザむナヌの安束ず申したす。 10/3、新サヌビスの「䞀䌑.comふるさず玍皎」がロヌンチしたした。 遞んだ宿がある自治䜓に寄附をするず、䞀䌑.comで䜿える割匕クヌポンを返瀌品ずしお、web䞊で受け取れるずいうサヌビスです。 䞀䌑.comの宿泊予玄ずは違ったサヌビスですが、予玄ぞず぀ながるサヌビスをどのようにデザむンに反映させたか、たた 䞀䌑.comの宿泊デザむンシステム の掻甚やFigmaを䜿ったこずを振り返りたす。 目次  ふるさず玍皎サむトで意識したこず  宿泊のデザむンシステムを掻かせるか  Figma導入埌、初のれロからデザむン  たずめ 1. ふるさず玍皎サむトで意識したこず サヌビスコンセプトのすり合わせ モックを䜜成するにあたりビゞネスサむドから、サヌビスの抂芁やタヌゲット局に加え、䞀䌑.com宿泊のUIを掻かしたい、ずにかくシンプルに などの芁望をもらいたした。たた、今回のプロゞェクトは、短期期間での開発ずいうこずもあり、䞻芁な導線の芁玠が倧筋決たっおいたので、画面むメヌゞを早く䜜り詳现をすり合わせながら「どんなナヌザヌ䜓隓にしたいか」のヒアリングや掘り䞋げ、他のデザむナヌからのフィヌドバックを受けながらの䜜成です。 デザむンにどう反映したか たずは既に䞀䌑.comを䜿っおいただいおいるナヌザヌがタヌゲットです。どのようにデザむンに反映したかたずめたす。 ナヌザヌが「寄附」ず「予玄」を混乱しないように 宿泊ず同様に宿から遞ぶのですがあくたで「寄附」をするサむト。宿の情報などは最䜎限にしお「予玄」に関する宿の情報やプランは、宿泊サむトで確認しおいただくような䜜りです。行き来するこずも考え、メむンずなる画像の芋せ方も差別化したした。 宿のカヌドも差別化のため、ベヌスは掻かし぀぀意図的にデザむンを倉曎しおいたす。 シンプルか぀スムヌズに 情報もシンプルにしたので、䜿甚する色も少なくし、目立぀アクセントカラヌをCTAボタンずしお寄附完了たでの道しるべを明確にするこずで、迷わずスムヌズに手続きいただけるよう意識したポむントです。 安心しお寄附しおいただけるように 高額の寄附か぀倉曎やキャンセルができないため、特に寄附やクヌポンに関する泚意事項の配眮や寄附金額・返瀌品ずしおもらえる割匕クヌポン額の衚瀺には気を付けたした。 2. 宿泊のデザむンシステムを掻かせるか ふるさず玍皎サむトを着手するの少し前から、宿泊では デザむンシステムの導入 を始めおおり、デザむンツヌルをXDからFigmaに移行し、デザむンコンポヌネントを倧小さたざたな粒床で䜜成しおいたす。こちらを掻甚するこずで宿泊のUIを掻かし぀぀、ふるさず玍皎サむトを組み立おようず考えたした。実装䞊はコンポヌネント化されおおらず、宿泊のように、デザむンずコヌドの連動はしおいたせん。 実際にどの郚分を採甚したか䞀郚をご玹介したす。 タむポグラフィヌ 䞀䌑らしさを担うタむポブラフィヌ党般曞䜓・サむズ・倪さはそのたた䜿甚しおいたす。 フォヌムのUI・パヌツ 䞀䌑.comのナヌザヌが䜿い慣れおいるUIを掻かすため、入力画面や決枈画面はペヌゞ党䜓、ラゞオボタンや入力フォヌムなどのパヌツもほがそのたた取り入れおいたす。 タブデザむン 実装面でも宿泊ず同様のTailwind CSSを採甚しおいたこずもあり、角䞞やシャドり、padding/marginなどの现かい郚分も同じように䜿えたのもよかったこずです。 このように別サヌビスでも、䞀䌑.comの宿泊デザむンシステムで定矩したデザむンの基本芁玠や粒床の现かいコンポヌネントが掻甚でき、「䞀䌑.comのUIを掻かしたい」にも繋がったのです。たた、掻甚したこずで統䞀や䞊蚘で挙げた郚分を考える時間は、他の䜜業に圓おるこずができたした。 user-first.ikyu.co.jp 3. Figma導入埌、初のれロからデザむン 宿泊でFigmaを䜿い始めた際、ツヌルの䜿い方に慣れず苊悩しおいたした。さらに、既存サヌビスである宿泊デザむンシステムではどのコンポヌネントにするかを珟状のデザむンを芋ながら考えおいたしたが、今回は新芏サヌビスであったため、珟状のデザむンはない状態で新しいデザむンの怜蚎やパタヌン出しをするこずに苊劎したした。慣れないツヌルず新芏サヌビスずいう2぀の難しさが重なったこずが蟛かったです。 テキストスタむル・色の定矩で倧倱敗、慣れるたで時間がかかった デザむンする䞭で、宿泊のコンポヌネントを倉曎しお䜿いたした。それは問題のないこずですが、ふるさず玍皎偎で新しく定矩する色を詊行錯誀しおいる段階では、Color Stylesで定矩せずに進めおいたした。 結果様々な画面でパタヌンを出した埌に定矩を远加したため、䜜成枈みのモックで色やテキストの眮き換え䜜業が発生しおしたいたした。 仮の状態で埌から埮調敎をするからこそ、定矩をしおおくべきでした。たた、色の遞考の際は定矩したカラヌリングごずにフォルダを䜜るなどをしお、Figmaの䟿利な機胜を掻甚できそうです。 コンポヌネントも散らかり気味で、同じようなものができたり、手動で眮き換え䜜業も䜕床もしたしたが、最終的にペヌゞを暪断しお䜿うコンポヌネントはたずめお管理し、ラむブラリずしお公開した埌は、倉曎を加えるず反映される状態になっおいきたした。ある皋床デザむンが固たったずきにコンポヌネントの芋盎し・敎理をするずいうのも倧事かもしれたせん。 4. たずめ デザむンに入る前に「どんなナヌザヌ䜓隓にしたいか」を掘り䞋げ事前に話し合ったこずで、新しい機胜や改善の際も、怜蚎䞭の時にそれがぶれおいないかず䞀぀の指暙になり、チヌムが同じ方向を向けたず思いたす。 たた、ふるさず玍皎では、宿泊のデザむンシステムがあっお本圓によかったず感じおいたす。統䞀感やスピヌドの面で掻かすこずができたためです。ただ、別サヌビスでも䜿甚するずいう目的で䜜られおいないため、今埌の扱いは改めお怜蚎する必芁はありそうです。 そんな䞭、䞀䌑のサヌビスを暪断したガむドラむンを䜜成するプロゞェクトが、デザむナヌ䞻䜓で始動したした。どのサヌビスを䜿っおもナヌザヌにずっお玠晎らしい䜓隓ができるよう、さらに進化をしおいる最䞭ですので、今回の経隓が少しでも圹立おばよいなず思いたす。 䞀䌑では、ずもに良いサヌビスを぀くっおいく仲間を積極募集䞭です。応募前にカゞュアルに面談をするこずも可胜ですので、お気軜にご連絡ください。 hrmos.co
こんにちは、プロダクト開発郚の野口です。 䞀䌑にはたくさんの斜蚭玹介ペヌゞがあるのですが、その䞭でもキュレヌションペヌゞずいう流入数が高いペヌゞがありたした。それをメむン動線であるリストペヌゞに統合したので、その経緯や裏偎をご玹介したす。 䞀䌑の斜蚭掲茉ペヌゞはたくさんある 䞀䌑には斜蚭をたずめお掲茉するペヌゞがたくさん存圚したす。 リストペヌゞ(メむン動線) https://www.ikyu.com/area/ma000000/t105/si1/?adc=1&asc=01&cid=20221008&cod=20221010&hoi=1,2&lc=2&mtc=003&per_page=20&pn=1&ppc=2&rc=1 キュレヌションペヌゞ https://www.ikyu.com/theme/t105/ 芳光ペヌゞ 特集ペヌゞ などなど。。。 その䞭でも今回はキュレヌションペヌゞをリストペヌゞに統合したずいうお話です。 どうしお統合したの キュレヌションペヌゞは怜玢するためのペヌゞずいうよりも、怜玢゚ンゞンからの流入口ずしお甚意されおいるものになりたす。そのため閲芧数は䞀䌑の䞭でもかなりいいほうなのですが、受動的な情報ばかりなので残念ながら予玄たでたどり着く割合は䜎かったのです。 䞀方でメむン動線であるリストペヌゞは怜玢に特化しおおり、ナヌザが胜動的に欲しい情報を芁求し、的確な情報を衚瀺できたす。そのため予玄たでたどり着く割合も高く、メむン動線ずしおの圹割をしっかりず党うしおいたす。 この2぀を統合するこずで流入数ず予玄割合のどちらも高めたいずいうのが狙いになりたす。 苊劎したこず キュレヌションペヌゞずいうのは、「地域xテヌマ」ごずにペヌゞが生成されおおり、斜蚭はランキング圢匏で衚瀺されおいたす。(先に掲茉した画像は各キュレヌションペヌゞの芪ペヌゞになりたす) 䞀方でリストペヌゞはさたざたな条件で怜玢ができるのですが、キュレヌションペヌゞず同じように「地域、テヌマ」による怜玢もできたす。しかもランキング圢匏での衚瀺もできるため、キュレヌションペヌゞず同じようなペヌゞを再珟できたす。 しかしながら、同じ条件で怜玢しおもキュレヌションペヌゞに衚瀺される内容ず異なるこずがあったのです。 原因はランキング生成ロゞックがそれぞれのペヌゞで異なっおいたからです。 もちろんどちらも八癟長ずいうこずはなくデヌタに基づいおランキングを生成しおいるのですが、现かい条件が少しず぀異なり、結果別の斜蚭が衚瀺されおしたったのです。 実装方針ですが、キュレヌションペヌゞには芪ペヌゞが存圚し、芪ペヌゞでもランキングを掲茉しおおり、その芪ペヌゞは残すずいう前提がありたした。そのためリストペヌゞにキュレヌションペヌゞのロゞックを持っおくる必芁がありたす。しかし䞀䌑ではアヌキテクチャを曎新しおいる最䞭で、キュレヌションペヌゞ偎は旧アヌキテクチャ、リストペヌゞ偎は新アヌキテクチャず別れおしたったためロゞックの移怍はしないこずにしたした。代わりにキュレヌション偎のアヌキテクチャで「゚リアIDずテヌマID」を受け取っおランキングを返すAPIを䜜成し、それをリストペヌゞのアヌキテクチャが叩くこずにしたした。 進捗は順調・・・かず思ったら・・・ 倧䜓のペヌゞではランキングの結果が䞀臎するようになり開発は順調かず思われたのですが、䞀郚のペヌゞに限っおランキングの結果が合わない状況に盎面したした。 キュレヌションペヌゞのURLをよくよく芋おみるず、なにやら芋たこずない数字がいたした。 https://www.ikyu.com/theme/a140000/g10/101/ 「a140000」は東京を衚す゚リアIDで、「101」ずいうのがテヌマIDになりたす。「g10」は䜕者だ・・・ キュレヌションペヌゞに詳しい方に聞いおみるず、どうやらキュレヌション関連のペヌゞ限定の抂念であるゞャンルIDをいうものもペヌゞ生成に圱響しおいるようで、「地域xテヌマ」ではなく「地域xテヌマxゞャンル」で生成されおいるずのこずでした。 ここで困ったこずが起きたした。 APIの方は単にゞャンルIDも指定できるようにすればよかったのですが、リストペヌゞではゞャンルIDずいう抂念がないため、そもそもAPIのパラメヌタに含めるこずができなかったのです。 ゞャンルIDを無芖するこずも怜蚎したのですが、それだずキュレヌション芪ペヌゞに衚瀺されおいる斜蚭ずリストペヌゞに衚瀺されおいる斜蚭が異なっおしたう可胜性がありたす。䞀䌑ではナヌザファヌストを掲げおいるため、そんな䜓隓は蚱されたせん。 そこでリストペヌゞのアヌキテクチャにゞャンルIDずいう抂念を組み蟌むこずにしたした。「リストペヌゞ」に組み蟌むのではなく、「アヌキテクチャ」に組み蟌みたす。このため圓初予定しおいたよりも倚くの改修が必芁になり、リリヌス予定日も延長しおしたいたした。 ですが、最終的には芁件を萜ずすこずなく、ナヌザ䜓隓も悪化させずにリストペヌゞに統合するこずができたした。先のリンクを開くずリダむレクトしおリストペヌゞが開くのですが、「g10」の郚分を倉えるこずで結果が倉わるこずを確認できるず思いたす。 統合を終えお 今回の統合では芁件を萜ずしたり、無理やり実装したりずいう郚分もいく぀かあったためちょっず悔しい思いも残っおいたす。 しかし蚪れた人が予玄した割合を比范しおみるず、統合前に比べお玄1.6倍ほどに増えおいたした。少しでも䜿い勝手が良くなったず思い、端的に嬉しかったです。 今埌のプロゞェクトでもより良い䜓隓を提䟛できるよう粟䞀杯努力しお参りたす。 hrmos.co
前回奜評だった䞀䌑ず出前通のオンラむン・むベント Frontend Meetup の第2回を開催したす。 むベント埌のアヌカむブ動画を公開したせんのでご興味がある方はぜひご参加ください 日時9/29(朚) 18:00~20:00 費甚無料 堎所オンラむンZoom お申し蟌みは以䞋のリンクからお願いしたす。 ikyu.connpass.com 時間 内容 登壇者 18:00 ご挚拶 18:05 - 18:25 䞀䌑. com/Yahoo!トラベルのNuxt3移行における開発プロセス 杉田 隆简 18:25 - 18:45 React 18 に芋るナヌザヌファヌストなロヌディング衚瀺 yoshiyamay 18:45 - 19:05 Testing for Demae-can App 黒柀 慎治 19:05 - 19:35 パネルディスカッション 20:00頃 終了
Apollo Client は耇雑 Apollo Client が向いおいるケヌス 䞀䌑.com に Apollo Client は必芁ないかもしれない では䜕を䜿えばいいの 耇雑なアプリケヌションには Apollo を䜿えばいい もう䞀぀のリッチなクラむアント、Relay の話 結局、䜕を䜿えばいいのか この蚘事は䞀䌑 × 出前通 Frontend Meetup でお話した内容をブログにたずめたものです。 user-first.ikyu.co.jp speakerdeck.com GraphQL クラむアントず聞いお䞀番に思い浮かぶラむブラリは䜕でしょうか 倚くの方にずっおは Apollo Client ではないかず思いたす。npm trends を芋おも Apollo Client のダりンロヌド数は urql や relay などほかのクラむアントず比べ圧倒的です。 実際、䞀䌑でも 䞀䌑.com や YADOLINK で Apollo を利甚しおいたす。 サヌビス GraphQL クラむアント 䞀䌑.com Apollo Clinet YADOLINK Apollo Client レストラン座垭管理画面 なし (axios) 新EC① urql 新EC② urql 新予玄管理画面 Relay しかし、Apollo Client は 「䞀番有名だから」ずいう理由で䜿っおいいほど無難なラむブラリではありたせん。どちらかずいえば、䜿い所を遞ぶ癖のあるラむブラリだず私は考えおいたす。 この蚘事は䞀䌑での採甚事䟋を亀えながら GraphQL クラむアントの遞び方に぀いおお話したす。もしかするず、Apollo Client はあなたのプロダクトに合っおいないかもしれたせん。 Apollo Client は耇雑 以䞋の図は䞻芁なクラむアントラむブラリをバンドルサむズが小さい順に䞊べたものです。これは正確な指暙ではありたせんが、バンドルサむズの倧きさず、機胜の豊富さ・耇雑さは比䟋しおいるず考えるず Apollo や Relay が比范的耇雑なラむブラリだずいうこずがわかりたす。 name minified + gzipped cross-fetch 2.8kB graphql-request 7.6kB urql 8.5kB @apollo/client 40kB react-relay 55kB バンドルサむズを小さくするために、別のクラむアントを䜿えず蚀っおるわけではないこずに泚意しおください。バンドルサむズも重芁ですが、"必芁最䜎限の機胜を持っおいるラむブラリを䜿う" こずが倧切です。 さお、GraphQL クラむアントの仕事ずは䜕でしょうか。突き詰めるず HTTP リク゚ストを発行しおAPIサヌバヌず通信するこずです。実は専甚のクラむアントを䜿わずずも fetch で GraphQL サヌバヌず通信ができたす。 では cross-fetch のようなシンプルなクラむアントず比べ、なぜ Apollo Client はこんなにもバンドルサむズが倧きいのでしょうか 通信以倖に Apollo が提䟛しおいる機胜ずは䜕でしょうか。 その答えは公匏ドキュメントに曞いおありたす。 Apollo Client is a state management library that simplifies managing remote and local data with GraphQL. ― Apollo Clientは、GraphQLを䜿甚しおリモヌトデヌタずロヌカルデヌタを簡単に管理できる状態管理ラむブラリです。 Apollo Client は "状態管理" ラむブラリなのです。 Apollo Client を導入する際は、たず「このアプリケヌションに状態管理ラむブラリは必芁か」ずいう問いに答えなければいけたせん。答えがNoであれば Apollo Client は必芁ありたせん。 か぀おSPAず状態管理ラむブラリはセットでした。どのプロダクトのコヌドを芗いおも必ず状態管理ラむブラリが入っおいたした。しかしグロヌバルな状態のデメリットが認知された珟代では、状態管理ラむブラリはアプリケヌションにずっおも必須のパヌツではありたせん。 Apollo Client が向いおいるケヌス Apollo Client が向いおいるアプリケヌションずはどんなものでしょうか Apollo Client は "Mutation が頻繁に発生し、か぀ Mutation 埌に refetch できない" 性質を持぀アプリケヌションで真䟡を発揮したす。䟋えば、Twitter や Instagram、我々が運営しおいるものだずYADOLINKのようなSNSに向いおいるでしょう。キヌワヌドは『無限スクロヌル』です。 YADOLINK 無限スクロヌルにより耇数ペヌゞのデヌタ取埗した埌、特定のアむテムに Mutation を実行するずきを考えおみたす。䟋えば、投皿に「いいね」するずいう操䜜です。「いいね」が完了するず、投皿のハヌトアむコンに色が付き、いいねがカりントアップしたす。 Apollo Client は Mutation のレスポンスを元に1ラりンドトリップで特定の投皿の倀を曞き換えたす。これは Apollo Client の特城である、"正芏化されたキャッシュ" のおかげです。 mutation { likePost ( postId : Int ! ) { postId likeCount isLiked } } 反応速床を少し犠牲にすれば、 Mutation 埌にペヌゞを䞞ごず再取埗するこずで同じこずが実珟できたす。実際、urql の Document Cache では Mutation 埌に関連するク゚リを再取埗するこずでUIを曎新したす。 しかし無限スクロヌルによるペヌゞネヌションを実装しおいる堎合は、珟圚の状態を埩元するために耇数ペヌゞ分のリク゚ストを発行する必芁があるため、すべおのデヌタを再取埗する戊略が珟実的ではありたせん。 逆に蚀うず、そもそも Mutation がほずんど発生しないアプリケヌションや、Mutation 埌にデヌタの再取埗によっおUIの曎新をするこずが蚱されるケヌスでは Apollo を䜿う必芁はありたせん。 䞀䌑.com に Apollo Client は必芁ないかもしれない さお、では Apollo Client を採甚しおいるもう䞀぀のアプリケヌション、我々の看板サヌビスである「䞀䌑.com」はどうでしょうか 実は䞀䌑.comは Query がメむンで Mutation がほずんど䜿われおいたせん。 ECサむトずいう性質䞊、䞀䌑䞊で発行されるリク゚ストのほずんどは "怜玢ク゚リ" です。最も重芁な操䜜である "予玄" はもちろん Mutation ですが、予玄凊理埌に別ペヌゞぞ遷移するので Mutation 埌にロヌカルの状態を曎新する必芁はありたせん。他にも、クヌポンの獲埗・お気に入りの远加ずいった Mutation がありたすが、これらもデヌタの再取埗をすれば十分です。 怜玢 ... Query 予玄 ... Mutation クヌポンの獲埗 ... Mutation お気に入りの远加 ... Mutation 倧は小を兌ねる、ずいう䞀面もあり Apollo Client は䞀䌑.comで必芁なナヌスケヌス "も" カバヌしおいるため、普段の開発では Apollo を䜿うデメリット感じるこずはほずんどありたせん。 しかし゚ッゞケヌスにおいお、過分なラむブラリを䜿っおいるせいでトラブルに巻き蟌たれるこずがありたす。たずえば、䞀䌑.com ではIEからのアクセスに察しお、Apollo の Store を fork した自前のキャッシュ機構を䜿うような実装になっおいたした。これは Apollo Client のキャッシュの正芏化がIE䞊の特定のデヌタで非垞に時間がかかっおしたうためです。ひず月以䞊の時間をかけお Apollo Client のコヌドを読み、workaround を実装したした。 たた、Apollo のプラグむンの察応状況が芳しくないせいで、Nuxt3 ぞのマむグレヌションが遅れおしたっおいたす。 もっず軜量なラむブラリを䜿っおいれば、こういったトラブルにも巻き蟌たれいなかったでしょう。自分たちが必芁な "䞀番ミニマムな実装" を採甚するこずが重芁だず孊びたした。 では䜕を䜿えばいいの では、Apollo が必芁ないずいうケヌスではどのクラむアントを䜿えばいいでしょうか urql や graphql-request がおすすめです。 Apollo が正芏化されたキャッシュを持぀のに察しお、urql は Document Cache ずいうシンプルなキャッシュ機構を採甚しおいる点が特城です。urql は Mutation の実行埌に Mutation の戻り倀ず同じ __typename を取埗しおいる Query をすべお再取埗したす。少し乱暎なようにも感じたすが、この方法で十分ずいうアプリケヌションも倚くあるはずです。 たた、Next.js を䜿っおいるなら swr + graphql-request ずいう組み合わせも良いでしょう。graphql-request はもっずもシンプルな GrapQL クラむアントで、状態管理機胜を持ちたせん。クラむアント固有の状態がなく、APIレスポンスのキャッシュずしお状態を扱うだけであればこの組み合わせがマッチしたす。swr は Vercel が䜜っおいるだけあっお、Next ず組み合わせおSSRするのも簡単なので芁件によっおはこちらを怜蚎しおみおください。 耇雑なアプリケヌションには Apollo を䜿えばいい ここたで、「シンプルなアプリケヌションにはシンプルな GraphQL クラむアントを䜿おう」ずいうお話をしおきたした。では、耇雑なアプリケヌションでは Apollo Clinet を䜿うのが正解なのでしょうか 実はそうではありたせん。耇雑なアプリケヌションの䞭には Apollo ず盞性が悪いものも存圚したす。それはサヌバヌのAPIキャッシュずは別に、リッチな状態を持぀アプリケヌションです。䟋えば、われわれが運営しおいるアプリケヌションだず、レストランの垭管理画面などがこれに該圓したす。 座垭管理画面 これは日付ごずに䜕垭を䞀䌑レストランに提䟛するかを管理する "圚庫カレンダヌ" ず呌ばれる画面です。カレンダヌ内で日付を遞んで、垭毎にその日の提䟛座垭数を決定したす。曜日䞀括操䜜などもあり、サヌバヌずすぐに同期しない状態操䜜が倚く存圚したす。 Apollo にはサヌバヌず同期する状態の他にロヌカル固有のデヌタを操䜜する機胜も提䟛しおいたす。これは Reduxや Vuex が提䟛する状態管理ず同等のものです。䞀䌑.com では䞀郚のこの Local State Management の仕組みを利甚しおいたすが...正盎なずころ Redux, Recoil などの専門の状態管理ラむブラリず比べおむンタヌフェヌスがこなれおおらず、あたり䜿いやすいずは蚀えたせん。 Apollo で "ロヌカルの状態管理もできる" こずは確かですが、耇雑な状態管理には玠盎に状態管理ラむブラリを入れるこずをおすすめしたす。この堎合は GraphQL クラむアントで状態管理する必芁はなくなるので、Recoil + graphql-request などの組み合わせ怜蚎するず良いでしょう。 䞊蚘の座垭管理画面では GraphQL クラむアントは䜿わずに axios でAPIサヌバヌず通信し、Vuex で状態管理を行っおいたす。axios で GraphQL の型の恩恵をあたり受けられおいないので...もし䜜り盎すずしたら axios ではなく、 graphql-request を䜿い、GraphQL Code Generator でコヌドず型の自動生成を行いたいです。 もう䞀぀のリッチなクラむアント、Relay の話 最埌に、Apollo Client ず䞊んで高機胜な Relay に぀いお少し觊れたす。Relay も正芏化されたキャッシュを持぀ GraphQL クラむアントです。ナヌスケヌスずしおは Apollo Client ずほが同じだず考えおいいでしょう。 では Apollo ではなく、 Relay を䜿うべきなのはどういったずきでしょうか 以䞋のケヌスでは Relay を怜蚎しおもいいでしょう。 コヌドの自動生成 + Fragment Colocation したい ペヌゞネヌションされた芁玠に察しお頻繁に芁玠の远加・削陀を行う React の Experimental な機胜をいち早く詊したい Relay には Relay Compiler ずいうコンパむラが付属しおいたす。コンパむラの仕事はコヌド内の graphql タグから型情報を含むファむルを自動生成するこずです。GraphQL Code Generator 盞圓の働きをしおいるずいうずわかりやすいかもしれたせん。たた Relay でアプリケヌションを䜜るず自然ず Fragment ず Component が䞀臎する Fragment Colocation スタむルになりたす。 Relay には䟿利なディレクティブがいく぀か远加されおいたすが、私が泚目しおいるのは @appendNode @prependNode ディレクティブです。これは connection に察する芁玠の远加を宣蚀的に行えるディレクティブです。Apollo Client で芁玠を远加する際は手続き的にはキャッシュを操䜜する必芁がありたすが、Relay ではそれらの操䜜はラむブラリ内に隠蔜されたす。Facebook で利甚されおいるだけあっおSNSを䜜るのに䟿利な機胜がほかにもありたす。 Relay は Meta 補のラむブラリだけあっお React の実隓的な機胜の取り蟌みが早いです。Suspense に぀いおも Suspense が Experimental の頃から察応しおいたした。今埌も先進的な機胜が先取りされる可胜性がありたす。ドキュメントが足りないのが懞念点ですが、トヌタルでは筋がよく、React ゚コシステムの未来を反映しおいるラむブラリだず考えおいたす。 䞀䌑ではずある新芏サヌビスの予玄管理画面を Relay を䜿っお開発䞭です。 瀟内向け管理画面のようなシンプルな管理画面にはシンプルな状態管理機構を持぀ graphql-rquest / urql が向いおいるず思いたす。ただ、この予玄画面はレストランの方も䜿うSaaSのような䜍眮づけの管理画面なのでUXを重芖しお Relay を採甚しおいたす。 YADOLINKはSNSですし、GraphQL Code Generator でのコヌド生成、Fragment Colocation も採甚しおいるため、珟圚リリヌス䞭のアプリケヌションの䞭ではYADOLINKが䞀番 Relay ず盞性が良さそうです。YADOLINKのアプリ版を React Native で䜜るこずを怜蚎しおいるので、その際は Relay が第䞀候補です。 結局、䜕を䜿えばいいのか さお、たずめです。 Apollo Client が圧倒的な知名床を持っおいるので Apollo Client を批刀するような内容になっおしたいたしたがそうではありたせん。 Apollo Client が向いおいるアプリケヌションもあれば、もっずシンプルなクラむアントで十分な堎合もありたす。 最埌に簡単なフロヌチャヌトを掲茉したす。 ECサむトや管理画面には Apollo は too much かもしれたせん。 Apollo Client や Relay、urql + GraphCache のようなリッチなクラむアントはSNSのようなナヌザヌの Mutation が頻繁に発生するサむトに向いおいたす。 GraphQL クラむアントの遞び方