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
17
技術的ミスと深堀り
2025/2/19に開催したRecruit Tech Conference 2025の雫石の資料です
Recruit
PRO
March 03, 2025
Tweet
Share
More Decks by Recruit
See All by Recruit
大規模プロダクトにおける フロントエンドモダナイズの取り組み紹介
recruitengineers
PRO
4
15
『ホットペッパーグルメ』における マルチプラットフォーム化の歩み
recruitengineers
PRO
2
10
『じゃらんnet』アプリ 改善活動の軌跡
recruitengineers
PRO
2
6
『スタディサプリ for SCHOOL』における Flutter導入とその成果
recruitengineers
PRO
2
9
よりよいビジネスの「実現」のために エンジニアリングを発揮する
recruitengineers
PRO
2
19
イテレーティブな開発で 不確実性を乗り越える
recruitengineers
PRO
2
6
株式会社リクルート 社内ISUCONの裏側
recruitengineers
PRO
1
13
エンジニア主導の企画立案を可能にする組織とは?
recruitengineers
PRO
1
22
人材領域での企業と求職者のマッチング最大化
recruitengineers
PRO
1
8
Other Decks in Technology
See All in Technology
ABWG2024採択者が語るエンジニアとしての自分自身の見つけ方〜発信して、つながって、世界を広げていく〜
maimyyym
1
120
AWSを活用したIoTにおけるセキュリティ対策のご紹介
kwskyk
0
340
Iceberg Meetup Japan #1 : Iceberg and Databricks
databricksjapan
0
330
PHPで印刷所に入稿できる名札データを作る / Generating Print-Ready Name Tag Data with PHP
tomzoh
0
180
LINE NEWSにおけるバックエンド開発
lycorptech_jp
PRO
0
220
Raycast Favorites × Script Command で実現するお手軽情報チェック
smasato
1
140
Visualize, Visualize, Visualize and rclone
tomoaki0705
9
82k
AI Agent時代なのでAWSのLLMs.txtが欲しい!
watany
2
220
php-conference-nagoya-2025
fuwasegu
0
150
【5分でわかる】セーフィー エンジニア向け会社紹介
safie_recruit
0
18k
Autonomous Database Serverless 技術詳細 / adb-s_technical_detail_jp
oracle4engineer
PRO
17
45k
【内製開発Summit 2025】イオンスマートテクノロジーの内製化組織の作り方/In-house-development-summit-AST
aeonpeople
2
610
Featured
See All Featured
A designer walks into a library…
pauljervisheath
205
24k
Imperfection Machines: The Place of Print at Facebook
scottboms
267
13k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Building Your Own Lightsaber
phodgson
104
6.2k
A better future with KSS
kneath
238
17k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
251
21k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
33
2.8k
The Art of Programming - Codeland 2020
erikaheidi
53
13k
Making the Leap to Tech Lead
cromwellryan
133
9.1k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
32
2.1k
Scaling GitHub
holman
459
140k
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の『接続』とは何だろ
う……?」となっていた気がする
まとめ • どの事例も、修正自体は軽微なもの
まとめ • どの事例も、修正自体は軽微なもの • しかし、そこから深堀りすると、物事の仕組みがわかって楽しい ◦ →私の楽しみ
まとめ • どの事例も、修正自体は軽微なもの • しかし、そこから深堀りすると、物事の仕組みがわかって楽しい ◦ →私の楽しみ • それが、類似の問題を防いだり、確実に解決したりすることにつながる ◦
→サービスの利用者、求職者や企業 / エージェントのため
まとめ • どの事例も、修正自体は軽微なもの • しかし、そこから深堀りすると、物事の仕組みがわかって楽しい ◦ →私の楽しみ • それが、類似の問題を防いだり、確実に解決したりすることにつながる ◦
→サービスの利用者、求職者や企業 / エージェントのため • 「私の楽しみ」と「サービス利用者のため」を両立させていきたい