1. ゆるITエンジニア道場
  2. 【2/3 システム設計編】ミドル..
2025-10-05 26:05

【2/3 システム設計編】ミドルクラスのフロントエンドのガチ面接

ほうれん草ボンバーさんをゲストにお迎えして、フロントエンドエンジニアのガチ面接をします。全部で3本構成です。


ほうれん草ボンバーさんが書いた図はこちら!

https://docs.google.com/presentation/d/1SZCyq5dKMFxRW25i4zCkIwyCkK6LhjPB0CMpf6QFjo8/edit?slide=id.g38eae37e858_4_16#slide=id.g38eae37e858_4_16


--------------------------------------------------------------


riddle : https://x.com/riddle_tec

ひびの : https://x.com/nasustim


番組へのお便りはこちら:https://forms.gle/gp78XNFgERDFDkb88

サマリー

このエピソードでは、システム設計に注目し、ほうれん草ボンバーさんとともにSNSのWebフロントエンドの設計プロセスを進めています。データの取得方法やコンポーネント設計、ページネーション、画像の最適化手法について詳しく議論されています。また、Reactを活用したフロントエンドの最適化手法や、SNSにおけるいいねボタンの実装に関する具体的なやり取りも行われています。機能追加の提案やAPIとの連携についても触れられ、システム設計面接の過程が描かれています。

システム設計の概要
こんにちは、シニアソフトウェアエンジニアのリドルです。 こんにちは、ミドルソフトウェアエンジニアのひびのです。
今日は前回に引き続き、ほうれん草ボンバーさんをゲストにお迎えして、技術面接の回を取っていこうと思います。
で、今回はなんとですね、システム面接会。 イエーイ、大変そう。
システム設計面接。 あのあれですね、よく外資とかそういうところであると言われているホワイトボードだーっと出して、
じゃあ今からこういうシステムを設計していただきます的なやつ。 ポッドキャストにマジで向いてない。
で、そうなんですよ。ポッドキャストに向いてないんですけど、いやこれ僕が面白そうだなと思って勝手に作っちゃったんですよ。
ありがとうございます。 おっしゃる通りポッドキャストに向いてないんで、これ収録が終わったらその最後ほうれん草ボンバーさんに設計していただいた
システム.pngをどこかにアップロードしようと思います。 はぁい。はい。で、ちょっと僕が今回用意できたのが
Googleスライドだけだったので、Googleスライド上でほうれん草ボンバーさんにシステムを設計していただこうかなと思います。
よろしくお願いします。ではですね、ほうれん草ボンバーさんがWebフロントエンドのエンジニアの方ということで、
で、僕あの実は某有名SNSの会社に勤めていまして、 なのでSNSのWebフロントエンドを作ってもらおうと思います。
おー、確かにこの前Mixi 2もね。 あーそうですね。あのMixi 2のWebフロントエンドエンジニアの方とたまに話す機会があって、
ちょっとそこで得た話も若干参考にさせていただいてます。まあその方、この前のMixi Tech Conferenceみたいなのに登壇してて、そこでバリバリ話してる内容ともかぶるんですが
やっていきましょうか。じゃあですね。 じゃあこれ本当に何も事前告知なしにぶつけてやるんですね。
すごいバッチリやるんですね。 まあまあまああのステップバイステップで簡単なところから徐々にシステムを作っていく。
でまあその中でほうれん草ボンバーさんがどういう切り口でどういう設計をするのかなということを見させていただこうかなと思います。
はい頑張ります。 ありがとうございます。ほうれん草ボンバーさんちなみにXとかMixi 2とかFacebookとか使ってらっしゃいますか。
はい使ってます。 おーじゃあ話が早い。じゃあ最初に前提から整理させていただくと
Webフロントエンドの面接なのでサーバー側としてはとても都合のいい紙APIがあることをという前提で進めたいと思います。
頼もしいですね。 紙APIがある。まあ行ってみたらWebフロントエンドからのリクエストの方法次第で1回でどんなデータでも取ってこれる
メッセージコンポーネントの設計
そういうAPIがあると仮定して進めましょう。 やばセキュリティがやばそうだ。
じゃあですねそうだな最初SNSってフォローしている友達の投稿が時系列に並ぶことが多いかな
そういった画面が一般的なSNSのトップビューとしてあると思うんですがじゃあまずはリアクトのコンポーネントと
あとフックスを組み合わせて 時系列にその投稿を並べる画面を作っていただきたい
ここで登場するのは本当にあのめちゃめちゃ大きいコンポーネントの名前とフックスの構成だけでいいです
例えばそうだな今例を書くとなんかユーズデータフェッチがあってリストがあってアイテムがあって
最初こんなリウドでいいんですがちょっとほうれん草ボンバーさんにざっくり作っていただければなと思います
分かりました
はいありがとうございます 本当に最初はシンプルなページングの想定でお願いできればなと思います
ではよろしくお願いします
はい頑張ります
まず僕が思ったのがやっぱりメッセージを取得しないといけないのでメッセージズっていうコンポーネントを作るかなと思いました
ありがとうございますそしてほうれん草ボンバーさんしっかり視聴者の方に分かりやすいように喋ってくださってありがたい
そしてメッセージズコンポーネントいいですね
作りますとでこのとてもとても都合のいい紙コンポーネントがあるのでこのコンポーネントを最大限利用させてもらって
ユーザーが投稿したメッセージ一覧を取得します
はいそういうAPIコールをかけるわけですね
今回ポイントになってくるのが投稿日時順にこのメッセージを整理しないといけないので
このメッセージコンポーネントの中のロジックとして投稿日時の順番にソートをかけます
なるほど
ポストバイト投稿日時の順番で項順に並べます
そうですね項順は
なので最新の投稿が一番上になっています
なるほどなるほど
このメッセージコンポーネントの中の一つ一つのメッセージ投稿を表示させていきますと
なのでこのメッセージテーブルの下にメッセージアイテムにしましょうかね一つ一つの投稿のコンポーネントを作ります
いいですね
ここに投稿内容とあとは投稿日時を表示させるとメッセージコンポーネントがメッセージアイテムコンポーネントを呼び出す
なるほどそうですね投稿したメッセージ一覧を取得がデータ取得を行うリアクトのフックスになるということですね
そうですねはいデータ取得は基本的にフックスを使って実装しています
なるほどなるほどちなみにじゃあもし API で何も指定しなかったらポスティトアットのデスクで返ってくるとしたらこれをどう変えましょうか
時系列順にもうすでにAPI からのレスポンスで返ってきてるってことですか
はいおっしゃる通りです
そうすると時系列順で並び替える必要がなくなるので相当かけるのがなくなって
取得した順番に投稿内容と投稿日時を表示させます
いいですね
今思いついたんですけどやっぱこれだったらメッセージ sns のメッセージ数って何万件もあるので
そうですね
これを一度に取得するのはちょっといくら紙 API と言えどもちょっとレスポンスが重くなる
なるほどなるほど
と思ったのでここはページネーションを使って投稿内容を100件ずつ取得するっていう風に設計しますね
そうですねおっしゃる通り sns の投稿が何万件何十万件とあったら
一度でデータを取得するのは難しいのでフロントエンドで順番に取ってくるっていう処理を含めるのは重要そうですね
ありがとうございます
パフォーマンスの最適化
じゃあここから要望がありました
ページネーション無限スクロールにしてみせたい
こういう時じゃあこのフックスとメッセージズコンポーネントそれぞれどう変えるかを実装していただけますか
はい無限スクロールだったら次の1件目のページネーションと2件目のページション
ページネーション起こるそのトリガーのタイミングが100件目のメッセージアイテムコンポーネントが表示されたタイミングでページネーションを行います
なのでページネーションのトリガーを100件目の投稿内容が表示されたタイミングにして
無限スクロールっていうのを実装しますね
なるほどなるほどそのメッセージズコンポーネントの100件目が表示されたタイミングで
あのフックスから渡されるコールバックか何かを再度実行させて再度データ取得を行うみたいな感じですかね
そうですそうです100件目が表示されたらフックス
なるほどなるほどじゃあどうぞ
表示されたらフックスでフックスが発火し次の100件が取得されるという実装にしますね
なるほどなるほどじゃあこの時のデータの管理メッセージ一つ一つの管理をどこでどうやって実装するかも簡単に書いていただいてもよろしいですか
データの管理投稿内容一つ一つの投稿内容をどうやって管理するか
そうですねあのAPIから取得した値をどういうデータの形式でもってあとページネーションするとなると追加したり削除したりみたいなアクションも発生しそうですね
はい状態管理に関してはそうですね使うライブラリとしてはUseContextを使って状態管理をします
管理する場所なんですがこのSNSアプリ全体の状態を管理したいのでこのメッセージコンポーネントの上にトップレイヤーとしてインデックスというかな
インデックス.TSXみたいなトップレイヤーのコンポーネントを置いてそこで状態管理を行います
そうですねあのインデックスあのトップレイヤーで状態を注入してアプリケーションどこからでも参照できるようにするということですね
はいそうですねここでだからあのユーザーのログイン情報であったり
メッセージが削除されているのかいないのかっていうメッセージの状態っていうのを管理します
メッセージのリストをじゃあそこで持ってでまぁページネーションが行われるたびにそちら側が更新されるということですね
そうですねページネーションがはいまあ100件の投稿内容を取得するたびに状態が更新される
なるほどなるほどそうですねいいですねなんかだいぶん大規模にあの情報展開できそうな設計になってきましたね
なるほどありがとうございますじゃあこれで満を持して無限スクロール機能が実装されました そしてリリースされました
おめでとうございますそこでユーザーからお問い合わせがありました 問い合わせの内容としては無限スクロールしたがら動作がめちゃめちゃ重くなってしまった
これは有意識問題ですねじゃあ動作がめちゃめちゃ重くなったという報告をもとにまずどこをまず何が原因かなとか当たりをつけていただいてもいいですか思いつく限りで大丈夫です
はいまあフロントエンドで言うと動作が重い原因は要はデータ量が画面に表示するデータ量が大きいっていうのが一番の原因だと思います
要は動画とか画像みたいなデータ量が多いリソースが画面の中にあるとどうしても動作が重くなる
なのでまずは僕がやるとしたらあの画像とか動画のデータの最適化を行いますね
なるほどなるほど具体的に画像や動画を最適化するにはウェブフロントエンドでやるとしたらどういった手法が考えられますか
よくやるのが遅延読み込み画面を表示するタイミングでは画像をまだ表示させずに
スペースだけ取っておくでその後に画像を順次読み込んでいく
そうすることによって画像以外のテキストの部分は先に表示されるのでユーザーからしたらそこまで待たされた感じがしない
なので画像の遅延読み込みっていうのはよくやりますね
なるほどなるほど確かにおっしゃる通り画像をいわゆるレジロードとかプリローディングみたいな仕組みを使って
重いリソースを後から取ってくるみたいなのはすごく重要ですねありがとうございます
一方でこれをやったとしても動作がどうも重いという時次どういう原因が考えられます
次考えられるのはレンダリングが何回も何回も起こっている
要はレンダリングが最適化されていないというところを疑います
いいですねおっしゃる通りそれもありえますね
じゃあレンダリングまあそれこそ100件ずつとしても例えばユーザーが画面をずっと見ていて
もう本当に何千件何万件とデータが表示されているっていうことも十分ありえますね
そういう時Webフロントエンド側で解決するとしたらどういう手法が考えられますか
そうですねよくやっているのがそのキャッシュを使うメソッド名で言ったらユーズメモとか
キャッシュを使うことによって無駄なレンダリングをさせないってことをよくやっています
状態管理の数が多くなってくると一つの状態がメッセージの状態が一つ変わるだけで
コンポーネントメッセージの中のコンポーネントをすべてもう1回レンダリングするという処理が走ってしまうので
キャッシュ戦略としてユーズメモとかあとはユーズコールバックとか
といったメソッドを使ってなるべく不要なレンダリングをさせないようにしています
Reactの最適化手法
いいですね確かにリアクトの最適化の手法として無駄なレンダリングを抑制するっていうのは十分効果がありそうですね
じゃあ逆にとはいえ1万件表示されているとそもそも画面に表示されるドムの数が多すぎて
ブラウザに負荷がかかっているみたいな状況だとどうでしょう何かできることはありますかね
フロンパイドラはねそうですね1万件ともなると特にスマホとかハードウェアが弱い端末で触ってたら
かなり画面表示が遅くなると思うのでその時は
そうだな画像の最適化のところにつながるんですけどあの画像の形式を
WebP とかあのかなり軽量の画像の形式に変えて生じさせますね
なるほどなるほど画像はリソースの管理の方をさらにチューニングをかけるという感じですね
そうですね
なるほどなるほどありがとうございますいろいろな案が出てきていいですね
いろいろな最適化の仕組みを取り入れてこのユーザーの画面がめちゃめちゃ重くなる問題が解決されたとの報告がありました
ありがとうございますほうれん草ボンバーさん
じゃあ次は企画の方から機能追加の要望がありました
このメッセージ一つ一つにいいねボタンを実装したい
はい
いいねボタンを実装したいという要望が来ました
じゃあいいねボタンを扱うためのコンポーネントとあとフックスそれぞれ用意していただけますか
はいいいねボタンなのでメッセージアイテムメッセーマー投稿内容一つ一つに付けられる機能
なのでメッセージアイテムコンポーネントのさらに下に作っていきます
いいですね
Likesボタンコンポーネントという名前で作っていきます
いいねボタンなので状態に関してはいいねしたかしていないかっていう2つの値だけなので
そうですね
ここに関してはわざわざユーズコンテクストとかで状態管理する必要はないかなと思うので
単純にユーズステートで状態管理をここでします
なるほどなるほどとするとじゃあ例えば自分が過去にもいいねした投稿がもう1回流れてきた時は
基本的にはユーズコンテクストの中に入っているメッセージ図に既にいいねしたよって情報があってそこから流し込まれると思うんですけど
それが一番最初レンダリングした時の初期値としてユーズステートに入るっていう理解でいいですかね
そうですねはいちょっと今の話聞いて確かに自分が過去にいいねした投稿なんだったっけって一覧表示する機能もこの後必要になってくるかなと思ったので
ありえますね
じゃあ基本的にはなるほどなるほど今表示しているコンポーネントとそれとは別で過去に過去にいいねした情報はもうメッセージ図の中に
APIから返ってきた値として含まれていてそこから注入されるものと2つあるわけですね
そうですねここはちょっと紙APIを頼ってですね投稿したメッセージ一覧と後もいいねしたメッセージ一覧が取れるAPIを
バックエンドの方に頑張って作っていただいてそこで取得しようかなと思います
なるほどなるほどじゃあここでついでになんですけどLikeボタンコンポーネントの方でいわゆるLikeを押したときに呼び出されるフックスも作っていただいていいですか
そうですね
行ってみたらLikeのAPIコールを行う機能かな
そうですねLikeボタンを押したらAPIリクエストが飛んでバックエンドのいいねメッセージ一覧ケーブルってところに追加されます
なるほどなるほどサーバー側の何かしかいいねを管理するデータソースがあってそこに登録されるということですね
これじゃあちょっともう少し詳細にここのデータフローを見ていきたいんですけどいいねのアクションですね
いいねボタンを押したときいいねボタンを押すAPIコールする後はいいねボタンの状態を変えて表示レンダリングされる結果を変えるみたいないくつかの処理があると思うんですけど
それを順番に箇条書きで書いていただけますか
言ってみたらいいねボタンを押してからユーザーがいいねしたことがわかるまでのフローです
まずはいいねボタンがユーザーを押しますそうすると状態が変わっていいねボタンがアクティブの状態になります
なるほどアクティブというのは具体的には
そうですねなんだろうハートマークが白色から赤色に変わる
なるほどなるほどウェブ上のハートマークに色が付くみたいな見た目の変化が起こるわけですね
多分そのタイミングで表示を変えるためにユーズステートにトゥルーが入るみたいな感じですかね
そうですねユーズステートがトゥルー
なるほどじゃあその後何か処理はありますか
その後自分がいいねしたもの一覧を見たいのでファヒーネリストに追加される
これヒーネリストはグローバルでユーズコンテキストで状態管理されている
なるほどヒーネリストがフロントエンドにあるということですね
なるほどなるほど
追加されて最後バックエンド側にも追加したいいねの投稿がリクエストされる
なるほどなるほど
じゃあこの4番APIでいいね自体がリクエストされたことをサーバー側に通知する
このAPI呼び出しにクライアント側エラーサーバーエラーか何かで失敗した時は何かしらの状態で何かしらの方法で失敗したことをフロントエンドが認知して
状態については再度整合性を保つみたいな処理が行われる理解でいいですかね
そうですね失敗した場合
それこそユーザーの画面には表示されているけどサーバー側ではその投稿が消されていたとかもありえそうです
システム設計面接の振り返り
あーなるほどちょっとちょっとそれ今聞いてちょっと方向転換します
あのいいねリストをそのフロント側で保持するのではなくてAPIがバックエンドのAPIからいいねリストを取得する実装の方がいいかなと思いました
おーなるほどなるほど言ってみたらサーバー側の情報をもう完全に整度してクライアント側ではあの状態としては何というか薄く持つというか
クライアント側で更新される状態ではなくするという扱いですかね
そうですねうちの方がデータ管理がしやすいなと思いました
そうですねそしていいねした投稿がポストされてあの3番と4番が入れ替わるって感じですね
なるほどありがとうございます
ありがとうございますいいですねなかなかSNSらしくなってきましたねここまで設計で
じゃあこれ見て僕からいわゆるシステム設計面接として見たいところは大体いい感じに見られたかなと思います
リドルさんにお返ししようかな何かありますか
そうですねちなみにほうれん草ボンバーさんこれあの投稿したメッセージ欄を最初に1回取得したとして
他の人が順次どんどん投稿していくじゃないですかそれをこうフェッチするにはどういうやり方が良さそうでしょうか
そうですね結構リアルタイム性が求められると思うのでSNSでは
何だろう一定期間を決めてデータフェッチを繰り返すっていう方法が良いかなと思います
例えば5秒ごとに更新がかかるとかそういった一定期間ごとにAPIの卒を何回もするっていう方法がいいかなと思います
具体的な技術としてはフォールループでスリープ5秒入れるみたいな感じですか
そうですねフォールループ
分かりましたありがとうございます
フォールループ
はいじゃあシステム面接は以上にしますか
はいということで今回はこれまでにしたいと思います
次回はですね今までの2つの面接の結果というか振り返りというかフィードバックを取る回としたいと思いますのでどうぞよろしくお願いします
よろしくお願いします
よろしくお願いします
ありがとうございました
ありがとうございました
26:05

コメント

スクロール