Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
技術的ミスと深堀り
Search
Recruit
PRO
March 03, 2025
Technology
3
100
技術的ミスと深堀り
2025/2/19に開催したRecruit Tech Conference 2025の雫石の資料です
Recruit
PRO
March 03, 2025
Tweet
Share
More Decks by Recruit
See All by Recruit
問題解決に役立つ数理工学
recruitengineers
PRO
9
2.5k
Curiosity & Persistence
recruitengineers
PRO
2
140
結果的にこうなった。から見える メカニズムのようなもの。
recruitengineers
PRO
1
310
成長実感と伸び悩みからふりかえる キャリアグラフ
recruitengineers
PRO
1
120
リクルートの オンプレ環境の未来を語る
recruitengineers
PRO
3
140
LLMのプロダクト装着と独自モデル開発
recruitengineers
PRO
1
190
新規検索基盤でマッチング精度向上に挑む! ~『ホットペッパーグルメ』の開発事例 ビジネス編
recruitengineers
PRO
2
120
新規検索基盤でマッチング精度向上に挑む! ~『ホットペッパーグルメ』の開発事例 技術編
recruitengineers
PRO
0
120
大規模プロダクトにおける フロントエンドモダナイズの取り組み紹介
recruitengineers
PRO
5
110
Other Decks in Technology
See All in Technology
AWS全冠芸人が見た世界 ~資格取得より大切なこと~
masakiokuda
4
4.8k
彩の国で始めよう。おっさんエンジニアから共有したい、当たり前のことを当たり前にする技術
otsuki
0
130
50人の組織でAIエージェントを使う文化を作るためには / How to Create a Culture of Using AI Agents in a 50-Person Organization
yuitosato
6
3.3k
AIエージェント開発における「攻めの品質改善」と「守りの品質保証」 / 2024.04.09 GPU UNITE 新年会 2025
smiyawaki0820
0
440
Рекомендации с нуля: как мы в Lamoda превратили главную страницу в ключевую точку входа для персонализированного шоппинга. Данил Комаров, Data Scientist, Lamoda Tech
lamodatech
0
630
【2025年度新卒技術研修】100分で学ぶ サイバーエージェントのデータベース 活用事例とMySQLパフォーマンス調査
cyberagentdevelopers
PRO
5
7k
Micro Frontends: Necessity, Implementation, and Challenges
rainerhahnekamp
2
430
Amazon CloudWatchで始める エンドユーザー体験のモニタリング
o11yfes2023
0
110
Lightdashの利活用状況 ー導入から2年経った現在地_20250409
hirokiigeta
2
280
”知のインストール”戦略:テキスト資産をAIの文脈理解に活かす
kworkdev
PRO
9
4.2k
Spring Bootで実装とインフラをこれでもかと分離するための試み
shintanimoto
7
700
LangfuseでAIエージェントの 可観測性を高めよう!/Enhancing AI Agent Observability with Langfuse!
jnymyk
1
180
Featured
See All Featured
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
13
1.4k
Building Better People: How to give real-time feedback that sticks.
wjessup
367
19k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
12k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
17k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
135
33k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
30k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
Automating Front-end Workflow
addyosmani
1369
200k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
What's in a price? How to price your products and services
michaelherold
245
12k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
129
19k
Transcript
技術的ミスと深堀り RECRUIT TECH CONFERENCE 2025 フロントエンドエンジニアが挑むプロダクト価値向上 雫石 卓耶 株式会社リクルート プロダクトディベロップメント室
雫石 卓耶 経歴 / Career 2021年に、リクルートへ新卒入社。社会人4年目。 HR系領域のWebフロントエンド / バックエンドエンジニア 現在は、『リクルートダイレクトスカウト』の開発メンバー
プログラミング。最近は、それ以外の趣味がないのが悩み 趣味 / Hobbies プロダクトディベロップメント室 アプリケーションソリューションユニット 横断エンジニアリング部 アプリケーションソリューショングループ
リクルートダイレクトスカウト • 転職スカウトサービス • 登録しプロフィールを入力すると、 企業 / エージェントからスカウトが届く • スカウトを受諾すると、企業
/ エージェント との、右のようなチャット画面が開く
開発メンバーの一員として • 普段から、技術的なミスをしてしまわないように注意している ◦ ミスが、求職者や企業 / エージェントの、利益や人生に影響して しまうかもしれず、それが怖いから
開発メンバーの一員として • 普段から、技術的なミスをしてしまわないように注意している ◦ ミスが、求職者や企業 / エージェントの、利益や人生に影響して しまうかもしれず、それが怖いから • しかし、システムからミスを完全に無くすのは難しいのも事実
Agenda 明らかになったミスに対して、私は深堀りを行うことがあります。どのような深 堀りを行ったのかについて、3つの事例をご紹介します。 • 事例1:データベースとnull文字 • 事例2:WebSocketとHTTP • 事例3:WebSocketのクローズ忘れ •
まとめ
事例1
事例1:データベースとnull文字 • 事例 ◦ チャット画面に入力されたメッセージをデータ ベースに挿入する際、null文字が含まれていて 失敗した • 補足 ◦
エラーの発生件数は1件だけ ◦ ユーザーへの直接の不利益は無し(メッセージ は通常通り見られる) • 対応 ◦ 入力内容からnull文字を排除する処理を追加
事例1の深堀り • 今回の件を単純化すると、反省点は「DBのvarchar(1)にどのような文字を挿 入できるか」がわかっていなかったこと • そもそも、「文字」はどのように表される? • DBの文字コード(charset)はUTF-8を使用
Unicodeと文字数 a U+61 コードポイント 各文字に一意なコードポイントが 割り振られている
Unicodeと文字数 a U+61 61 UTF-8 コードポイント バイト列 コードポイントをエンコードしてバイト列を得る。 バイト列は、ファイルへの読み書きや、通信などで使用される
Unicodeと文字数 a U+61 61 UTF-8 コードポイント バイト列 仮説1:バイト数を文字数としている?
複数のバイトにエンコードされる文字もある a U+61 61 UTF-8 コードポイント バイト列 あ U+3042 E3
81 82 UTF-8 1バイトに収まらない 複数バイトにエンコード
複数のバイトにエンコードされる文字もある a U+61 61 UTF-8 コードポイント バイト列 あ U+3042 E3
81 82 UTF-8 バイト数を数えると 「あ」は3文字になる
複数のバイトにエンコードされる文字もある a U+61 61 UTF-8 コードポイント バイト列 あ U+3042 E3
81 82 UTF-8 仮説2:コードポイント数を 文字数としている?
複数のコードポイントで表現される文字もある 文字画像の出典: https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:U845b-k.svg https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:U845b.svg 「かつしかく」 の1文字目 「かつらぎし」 の1文字目 U+845B U+E0101
U+845B U+E0100
複数のコードポイントで表現される文字もある 文字画像の出典: https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:U845b-k.svg https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:U845b.svg 「かつしかく」 の1文字目 「かつらぎし」 の1文字目 U+845B U+E0101
U+845B U+E0100 基底文字としては区別されない
コードポイントは、文字の同一性ごとに割り当てられる • Unicodeは、文字の形の詳細に立ち入らない ◦ 文字の形はフォントが決める • いろいろな「a」があるが、抽象的には同一の文字 • 同一の文字なので、おなじコードポイントが割り当てられている 表の出典:
Unicode® Technical Report #17: Unicode Character Encoding Model, https://www.unicode.org/reports/tr17/
複数のコードポイントで表現される文字もある 文字画像の出典: https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:U845b-k.svg https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:U845b.svg 「かつしかく」 の1文字目 「かつらぎし」 の1文字目 U+845B U+E0101
U+845B U+E0100 異体字: 見た目は異なるが意味は同じ文字 →同一な文字とみなされて同じコードポ イントが割り当てられた →賛否両論あったらしい
複数のコードポイントで表現される文字もある 文字画像の出典: https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:U845b-k.svg https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:U845b.svg 「かつしかく」 の1文字目 「かつらぎし」 の1文字目 U+845B U+E0101
U+845B U+E0100 異体字セレクタによって指定できる
複数のコードポイントで表現される文字もある a U+61 61 UTF-8 コードポイント バイト列 あ U+3042 E3
81 82 UTF-8 U+845B U+E0100 E8 91 9B F3 A0 84 80 UTF-8 コードポイント数を数えると は2文字になる
複数のコードポイントで表現される文字もある a U+61 61 UTF-8 コードポイント バイト列 あ U+3042 E3
81 82 UTF-8 U+845B U+E0100 E8 91 9B F3 A0 84 80 UTF-8 書記素クラスタを使うと、 「ユーザが認識する『文字』の境界」 を決定できる。 仮説3:書記素クラスタ数を 文字数としている?
どの仮説が正しい? • 仮説1:バイト数? • 仮説2:コードポイント数? • 仮説3:書記素クラスタ数?
実験してみた • 使用しているDBMSはPostgreSQL • varchar(1)の列を定義し、いろいろな文字を挿入してみた ◦ a(U+0061):挿入可 ◦ あ(U+3042):挿入可 ◦
(U+845B U+E0100):挿入不可 • →文字数は、コードポイント数でカウントされるようだ(仮説2が正しそう) • →varchar(1)には「コードポイント1つ分」が挿入できそうだ
すべてのコードポイントが挿入可能なのか? null文字(0x0000)以外のすべてのコードポイントを挿入するプログラムを作成 してみた Unicodeコードポイント(約110万個) 0 0x10ffff
すべてのコードポイントが挿入可能なのか? null文字(0x0000)以外のすべてのコードポイントを挿入するプログラムを作成 してみた →一部の範囲のコードポイントが挿入できなかった Unicodeコードポイント(約110万個) 0 0x10ffff
すべてのコードポイントが挿入可能なのか? Unicodeコードポイント(約110万個) 0 0x10ffff UTF-16のサロゲートペアに使用される領域。 単独では文字を表さない
すべてのコードポイントが挿入可能なのか? Unicodeスカラ値(USV) 0 0x10ffff
すべてのコードポイントが挿入可能なのか? Unicodeスカラ値(USV) 0 0x10ffff varchar(1)にどのような文字を挿入できるか? →USV - {0}の任意の値1つ(PostgreSQLでは)
追加の調査 • フロントエンドやバックエンドでは、バリデーション処理で文字数を数えて いる。このカウント方法はコードポイント数によるか? そうでない場合、 DBのカウント方式と差異があるが、おかしな挙動にならないか? • サロゲートペアが単独で入力されることはないか? された場合、DBではエ ラーになるが、システム全体としてはどうなる? →深堀りを行うことで、新しい観点が得られ、横展開調査ができた →結果としては問題なかった
事例2
事例2:WebSocketとHTTP • 背景 ◦ チャット機能では、メッセージサーバーとの通 信をWebSocketで実現している • 事例 ◦ リリース前試験において、リクルート社内の一
部のセキュリティが厳しい環境で、チャット機 能が使えない • 補足 ◦ その環境では、ファイアウォールにより、あら かじめ許可された種類の通信しかできない
チャット機能の通信を許可してもらうことに ファイアウォール担当「WebSocket通信を利用したいのですね。であれば、 HTTPの許可は不要ですかね? TCPポートだけ許可すれば良いですか?」
チャット機能の通信を許可してもらうことに ファイアウォール担当「WebSocket通信を利用したいのですね。であれば、 HTTPの許可は不要ですかね? TCPポートだけ許可すれば良いですか?」 私「はい……おそらくHTTPの許可は必要ないと思います……? TCPポートは 443番を使用しているようなので、許可していただけますか……?」
チャット機能の通信を許可してもらうことに ファイアウォール担当「WebSocket通信を利用したいのですね。であれば、 HTTPの許可は不要ですかね? TCPポートだけ許可すれば良いですか?」 私「はい……おそらくHTTPの許可は必要ないと思います……? TCPポートは 443番を使用しているようなので、許可していただけますか……?」 →TCPだけ許可してもチャット機能は使えず
チャット機能の通信を許可してもらうことに ファイアウォール担当「WebSocket通信を利用したいのですね。であれば、 HTTPの許可は不要ですかね? TCPポートだけ許可すれば良いですか?」 私「はい……おそらくHTTPの許可は必要ないと思います……? TCPポートは 443番を使用しているようなので、許可していただけますか……?」 →TCPだけ許可してもチャット機能は使えず 私「あっ、やっぱりHTTPも関係するみたいなので許可をお願いします……」 →ようやくチャット機能が利用可能に
私は、WebSocketのことを 何もわかっていない……
私の趣味 • プロトコルスタックの自作 ◦ イーサネット〜TCPまでの、C言語での簡易的な自作実装はすでにあっ た • イーサネット〜WebSocketまでを(簡易的にでも)全部実装すれば、理解を 深められるかもと思った •
送ったデータをそのまま返す、WebSocket Echoサーバーを実装してみる
実装したWebSocket Echoサーバーの動作
TCP接続をパッシブオープン • クライアントからのWebSocketリクエストを待ち受け
クライアントからの最初のリクエスト • GET / HTTP/1.1 • Host: xxx • Upgrade:
websocket ◦ WebSocket通信にアップグレードしたいと言っている • Connection: Upgrade • Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== ◦ 次に応答を返すために必要 • Sec-WebSocket-Version: 13
サーバーからのレスポンス • HTTP/1.1 101 Switching Protocols • Upgrade: websocket •
Connection: Upgrade • Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= ◦ 先ほどのSec-WebSocket-Keyに、仕様で決まっているマジックナンバーを追 加し、sha1をとって更にbase64エンコードしたもの ◦ 正しい手順でWebSocket要求が受け入れられたことをクライアントに示す →WebSocket接続完了 →先ほどのファイアウォール問題で、TCPだけでなくHTTPも許可する必要があった理由
ここから先はバイナリで通信する • 以下のような形式のバイナリデータがTCPソケットで送られてくる • 仕様通りにフラグやマスキングの処理を行うと、ペイロードが得られる • 同じようにして、ペイロードをそのまま返却すると…… 出典:FETTE, Ian; MELNIKOV,
Alexey. Rfc 6455: The websocket protocol. 2011.
動作した! →うれしい
事例3
事例3:WebSocketのクローズ忘れ • 事例 ◦ チャット画面を閉じた後も、WebSocketの接続が残り続けてしまう場合 がある ▪ システムに余分な負荷がかかってしまう • 原因
◦ WebSocketのクローズ処理の実装漏れ • 対策 ◦ クローズ処理を追加する
チャット画面を開閉してChrome DevToolsの表示を確認 クローズ処理の追加前後で、通信状況を比較してテスト クローズ処理追加前 クローズ処理追加後 →この表示だけを証拠に「接続が閉じた」と判断するのは心もとなかった
WebSocketについて学んだ今なら • 「WebSocketの通信=TCPソケット」とわかっている ◦ →OSのTCPスタックに問い合わせれば状況がわかる ◦ ESTAB状態のソケット数の増減を調べることで、確実にWebSocketがク ローズされていることを確認して、修正をリリースできた • 学んでいなかった以前の私なら「そもそもWebSocketの『接続』とは何だろ
う……?」となっていた気がする
まとめ • どの事例も、修正自体は軽微なもの
まとめ • どの事例も、修正自体は軽微なもの • しかし、そこから深堀りすると、物事の仕組みがわかって楽しい ◦ →私の楽しみ
まとめ • どの事例も、修正自体は軽微なもの • しかし、そこから深堀りすると、物事の仕組みがわかって楽しい ◦ →私の楽しみ • それが、類似の問題を防いだり、確実に解決したりすることにつながる ◦
→サービスの利用者、求職者や企業 / エージェントのため
まとめ • どの事例も、修正自体は軽微なもの • しかし、そこから深堀りすると、物事の仕組みがわかって楽しい ◦ →私の楽しみ • それが、類似の問題を防いだり、確実に解決したりすることにつながる ◦
→サービスの利用者、求職者や企業 / エージェントのため • 「私の楽しみ」と「サービス利用者のため」を両立させていきたい