Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
技術的ミスと深堀り
Search
Recruit
PRO
March 03, 2025
Technology
3
200
技術的ミスと深堀り
2025/2/19に開催したRecruit Tech Conference 2025の雫石の資料です
Recruit
PRO
March 03, 2025
Tweet
Share
More Decks by Recruit
See All by Recruit
事業の財務責任に向き合うリクルートデータプラットフォームのFinOps
recruitengineers
PRO
2
24
AI-DLCを現場にインストールしてみた:プロトタイプ開発で分かったこと・やめたこと
recruitengineers
PRO
2
160
プロダクトマネジメントの分業が生む「デリバリーの渋滞」を解消するTPMの越境
recruitengineers
PRO
3
830
あなたの知らない Linuxカーネル脆弱性の世界
recruitengineers
PRO
4
320
dbtとBigQuery MLで実現する リクルートの営業支援基盤のモデル開発と保守運用
recruitengineers
PRO
5
250
『ホットペッパービューティー』のiOSアプリをUIKitからSwiftUIへ段階的に移行するためにやったこと
recruitengineers
PRO
4
1.8k
経営の意思決定を加速する 「事業KPIダッシュボード」構築の全貌
recruitengineers
PRO
4
410
Browser
recruitengineers
PRO
12
4k
JavaScript 研修
recruitengineers
PRO
9
2.2k
Other Decks in Technology
See All in Technology
新 Security HubがついにGA!仕組みや料金を深堀り #AWSreInvent #regrowth / AWS Security Hub Advanced GA
masahirokawahara
1
2.2k
ディメンショナルモデリングを支えるData Vaultについて
10xinc
1
110
ウェルネス SaaS × AI、1,000万ユーザーを支える 業界特化 AI プロダクト開発への道のり
hacomono
PRO
0
140
子育てで想像してなかった「見えないダメージ」 / Unforeseen "hidden burdens" of raising children.
pauli
2
270
Oracle Cloud Infrastructure IaaS 新機能アップデート 2025/09 - 2025/11
oracle4engineer
PRO
0
160
OCI Oracle Database Services新機能アップデート(2025/09-2025/11)
oracle4engineer
PRO
1
210
regrowth_tokyo_2025_securityagent
hiashisan
0
250
JEDAI認定プログラム JEDAI Order 2026 エントリーのご案内 / JEDAI Order 2026 Entry
databricksjapan
0
140
Strands Agents × インタリーブ思考 で変わるAIエージェント設計 / Strands Agents x Interleaved Thinking AI Agents
takanorig
2
150
[デモです] NotebookLM で作ったスライドの例
kongmingstrap
0
160
生成AIを利用するだけでなく、投資できる組織へ / Becoming an Organization That Invests in GenAI
kaminashi
0
110
ChatGPTで論⽂は読めるのか
spatial_ai_network
11
29k
Featured
See All Featured
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
1.8k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
359
30k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
196
70k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.3k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.6k
GraphQLとの向き合い方2022年版
quramy
50
14k
A designer walks into a library…
pauljervisheath
210
24k
Why Our Code Smells
bkeepers
PRO
340
57k
Designing Experiences People Love
moore
143
24k
Navigating Team Friction
lara
191
16k
Code Reviewing Like a Champion
maltzj
527
40k
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の『接続』とは何だろ
う……?」となっていた気がする
まとめ • どの事例も、修正自体は軽微なもの
まとめ • どの事例も、修正自体は軽微なもの • しかし、そこから深堀りすると、物事の仕組みがわかって楽しい ◦ →私の楽しみ
まとめ • どの事例も、修正自体は軽微なもの • しかし、そこから深堀りすると、物事の仕組みがわかって楽しい ◦ →私の楽しみ • それが、類似の問題を防いだり、確実に解決したりすることにつながる ◦
→サービスの利用者、求職者や企業 / エージェントのため
まとめ • どの事例も、修正自体は軽微なもの • しかし、そこから深堀りすると、物事の仕組みがわかって楽しい ◦ →私の楽しみ • それが、類似の問題を防いだり、確実に解決したりすることにつながる ◦
→サービスの利用者、求職者や企業 / エージェントのため • 「私の楽しみ」と「サービス利用者のため」を両立させていきたい