## プロジェクト概要
1万社以上が利用するアルバイトや派遣領域の採用管理システムのWebエンジニアをしています。
要件確認・ドキュメント作成・テストケース作成・実装・結合テスト実施など一連の流れに沿いアジャイル開発をしています。
具体的には、APIレスポンスの設計・実装や非同期処理のパフォーマンス改善、管理画面の実装などバックエンド・フロントエンド問わずしています。
## チーム構成
開発体制はスクラム開発でPM、QA、EM、デザイナー、フロントエンド・バックエンドエンジニア(外部企業エンジニア含む)合わせて25名で構成。
エンジニアは1~6名でドキュメント作成・テストケース作成・実装・結合テスト実施まで行い、各作業でPM, QA, EM, デザイナーと相談・レビューを行いながら、タスクを進めていきます。
その中でフロントエンド・バックエンドエンジニアを担当しています。
## 自身の役割
不具合修正、パフォーマンス改善、機能開発を行っています。
## 開発・実装内容
### 外部APIとの汎用連携機能・管理画面開発
連携する採用媒体を持つ企業にAPIを用意してもらい、APIの登録・管理を行う。
「連携の流れ」
1. 媒体追加で連携したいAPIのURLを登録するとアクセストークンが発行される。
2. それを連携先の企業に渡して、APIに設定してもらう。
3. 設定後、連携確認を行う。
4. 連携が確認出来たら、連携した採用媒体を選択出来るようになり、応募者が取り込める。
**【課題・問題点】**
採用媒体から応募者を取り込んで、管理する機能があります。
取り扱う採用媒体を新規に追加する際、クローラを書いて手作業で追加していました。
そのため追加するのに**工数が多くかかる**という課題がありました。
そして、すでに主要な採用媒体は取り扱われているため、地方で取り扱われていてユーザ数の多い採用媒体を少ない工数で追加し**販路を拡大**しようという策略もありました。
これらの課題解決・策略実施するためバックエンド2名、フロントエンド1名で新機能実装を行いました。
その中で**自分はフロントエンドを担当**しました。
**【使用技術、実装方法】**
React, TypeScript, React Routerで実装された管理画面に新たにパスを切り下記の画面を加えました。
- 媒体一覧:2つのAPIからJSONで返る未連携・連携済みの媒体を2つのテーブルレイアウトに分けて表示。
- 媒体追加:フォーム入力画面で文字列、真偽値を取得してAPIに送信。この時にレスポンスでアクセストークンが返り媒体詳細に遷移。
- アクセストークン:媒体追加から遷移時にhistory.pushでstateを渡して、遷移先でアクセストークを受け取り表示。そして一度、画面更新を行うとstateが空になるためアクセストークン画面が非表示となる実装。
- 媒体詳細 :APIから媒体の詳細情報をJSONで受け取り表示。その際に未連携・連携済みでレイアウトを変更。未連携の場合は連携ボタンが表示されておりクリックすると連携処理を実行。APIにリクエストが送信されてローディングのアニメーションを表示。
- 媒体編集:登録された媒体の情報をフォームに反映し、データを取得しAPIに送信。連携後に媒体を公開する企業の選択が可能なため企業を検索して公開範囲に選択するフォームが追加で実装。
これらの画面をデザイナーと協力して、Figmaを活用しながらを新規作成・実装部分を担当しました。
**【工夫した所、及び成果】**
- チーム開発
- APIとやりとりする際のデータ形式について、バックエンドエンジニアの方に相談し、受け取った後フロントエンドに処理を持たせなくても良いデータ形式を意識しながら設計しました。それによりAPI繋ぎ込み時の認識齟齬を減らす事で実装時の工数削減、不要なデータ操作を減らしパフォーマンスと可読性に貢献しました。
- 実装
- アクセストークンの取り扱う実装をした事がなく仕様に悩みました。そこでGitHubのアクセストークン発行画面を参考に一度しか表示されないようセキュリティに貢献した実装を行いました。
- 公開範囲のフォームでは、無限ローディングの実装を行いました。連携済み媒体を表示させたい企業が大量に表示されるケースを想定して実装しました。データ形式をオブジェクトで持つ事で、1万件のkeyを持つオブジェクトが読み込まれても表示設定の切り替えが行えるようにパフォーマンスを意識した実装に貢献しました。
- 開発
- 上記の事を意識しながら実装した結果、チームのサポートもあり納期通り開発が完了し、リリース後は取り扱う採用媒体を増やしながら、安定的に使用され販路拡大に貢献しています。
公開範囲フォームのデータ構造等、詳細な実装は下記の記事で解説しています。
https://techlog.n2i.jp/entry/2023/07/03/110236
**【振り返ってどう思うか・学んだ点】**
データ操作の責任をフロントエンドに持たせてしまうと、処理が複雑になりパフォーマンスにも影響するのでなるべくバックエンドに持たせるべきだと思いました。そしてフロントエンドでは受け取ったデータを表示のみに責任を持たせるべきだと思いました。
チームで開発する上で曖昧な要件、受け渡すデータ形式について事前に話しておく事で実装後の手戻りも減らせると思いました。
### 管理画面の表示設定実装
取り扱える採用媒体一覧で特定分野の採用媒体の表示を各画面で制御する。
**【課題・問題点】**
特定分野の採用が伸びてきおり、該当する採用媒体を追加して販路を拡大するという話が出てきた。
しかし、その採用媒体の取り扱いしている事を利用者様に知られると、**サービスのイメージに影響する**可能性がありました。
そのため、特定の企業でのみしかその採用媒体は表示されないよう、管理画面から制御する機能実装を行いました。
これらの課題解決・策略実施するためバックエンド2名で特定の採用媒体から応募者を取り込む機能を開発、管理画面から追加した特定の採用媒体の表示を制御出来る機能開発を行いました。
自分は**後者の特定の採用媒体を表示を制御出来る機能開発を担当**しました。
**【使用技術、実装方法】**
Ruby on Railsで構築されたAPIモードのアプリケーションに下記の変更を行いました。
- モデルに表示設定を管理するカラムを追加。
- 新規APIを作成し表示設定に合わせて返す採用媒体一覧を変更。
- 各画面で新規作成したAPIから受け取った採用媒体を使用するよう変更。
- 各APIメソッドのテストコードを追加。
**【工夫した所、及び成果】**
- 実装
- 既存機能への影響範囲が広く、関連するメソッドは68箇所に及びました。書き出しまとめた物を元にEMと相談を重ねながら仕様を固めていきました。そして、フロントエンドにハードコーディングされていた採用媒体一覧を解消して、バックエンドから返すように変更しました。これにより、採用媒体一覧の変更が発生してもバックエンドから操作出来るようになりました。機能拡張し易い設計となり外部APIとの汎用連携機能・管理画面開発を実装する際に貢献しました。
- 開発
- 関連するメソッドを書き出していた事もあり、テストで変更箇所を細かく確認できました。リリース後に問い合わせ・不具合は発生する事なくその採用媒体を追加出来ました。一般企業に影響を与える事なく販路拡大に貢献しました。
**【振り返ってどう思うか・学んだ点】**
既存機能への機能追加はコアな機能であるほど影響範囲は膨大になると学びました。そしてその際は使用される各メソッドを追い把握した上で実装を進める事でのちに発生する不具合・考慮漏れを軽減出来ると思いました。
泥臭いがメソッドを書き出して追うことは大事だと思いました。
フロントエンドにデータを持たせることは負債に繋がると思いました。
### 通知処理、応募者検索のパフォーマンス改善
毎時間実行される、通知処理のworkerパフォーマンス改善と応募者検索時のslow query改善
**【課題・問題点】**
各通知処理が重く、worker内で複数の通知処理が一度に並列で実行されるため **処理が集中して負荷が発生** していた。そして **NewRelicで高負荷アラートが発生** していた。通知処理の部分を確認すると将来的に応募者のデータが増えた際にメモリを圧迫する箇所が見られた。検索処理で **重くなるクエリー** も見られた。
これらの課題を解決するためにパフォーマンス改善を行いました。
**個人で担当**しました。
**【使用技術、実装方法】**
Ruby on Railsで構築されたAPIモードのアプリケーションに下記の変更を行いました。
- 各通知処理でN+1が発生していたので、それらの解消。
- workerの実行時間を分散を10分間どこかで実行するように変更。`worker.perform_in(rand(1..DELAY_MAX_SEC).seconds, t)`
- in_batchesを使用して、将来的なメモリ圧迫による負荷予防。
- 検索が遅くなるクエリーに対しては、検索の対象となるカラムが複数のため複合インデックスを貼り解消。
**【工夫した所、及び成果】**
- 実装
- 変更後パフォーマンスに改善が見られるか本番と同じように大量の通知を送信する、応募者を大量に用意するスクリプトを作成し検証を行いました。結果としては変更前・後で通知処理が最長レスポンスに7秒かかる所、最長レスポンスで3.5秒にまで短縮しました。応募者検索のslow queryでは変更前・後で43msかかる検索処理を0.06msまで改善しました。パフォーマンス改善に貢献する事が出来ました。
- 開発
- 作成したスクリプトが周辺のパフォーマンス改善を担当メンバーの検証でも使用され、工数削減に貢献しました。
**【振り返ってどう思うか・学んだ点】**
ユーザ数が多いサービスではパフォーマンスを気にかけた設計を行わないと、ボトルネックが発生する事が分かりました。これは個人開発では学べない事なのでとても楽しくもあり、大事だと思いました。
そしてそれを地道に解消する事がかなりのパフォーマンス改善につながる事を学びました。
このタスクを行う前はバックエンドの知識が乏しかったのですが、SQLを読んだりN+1とはどういう状態なのかループ処理は大量のデータを取り扱う際メモリをすぐに圧迫してしまうという事を学びました。
### agora v3を使用した複数人同時Webビデオ通話機能のagoraバージョンをv4にリプレイス
既存の仕様に変更なくagoraのバージョンを上げる
**【課題・問題点】**
Chromeバージョン更新時、agoraを用いた **ビデオ通話機能が使えない事案が発生** していた。
agora v3の **サポート期限切れ** が近づいており、このままではChromeバージョン更新によりビデオ通話機能が使えなくなる事が予想されました。
ビデオ通話機能はオプション販売されている機能でもあり、売り上げに繋がるためサポートが切れる前に更新する必要がありました。
**個人で担当**しました。
**【使用技術、実装方法】**
React, TypeScript, agoraライブラリで実装されたビデオ通話機能に下記の変更を加えました。
- v3 → v4 では破壊的変更が行われており多くのメソッドをv4用に変更する必要がありました。
- v3用のagoraコミュニティで作成されたライブラリ(agora-stream-player)も使用されており、削除しました。そして受信したビデオを再生する部分のみ必要なためライブラリの参考にReactコンポーネントを作成しました。
- 画面共有機能でステート管理が上手くいかず待機処理があった箇所の解消、それにより画面共有実行時の動作速度改善。
- 画面共有時自身のトラックをサブスクライブして重複料金が発生していたのでそちらの箇所修正。
**【工夫した所、及び成果】**
- 実装
- agora側の判定バグでiPhone ios 15.7 Safariでブラウザチェックが失敗するため、問い合わせを行いました。そこでライブラリのバグと判明し緊急処置としてios safariの判定処理を追加、注意文言を表示することによって、ユーザがサポートブラウザにも関わらずWeb面接を使わない機会損失しないように貢献しました。
- 画面共有機能の動作速度を改善、重複料金が発生していた箇所の改善、不要なライブラリを使用しないよう実装するなどバージョン上げ以外に周辺の修正も行いました。結果としてパフォーマンス改善できユーザビリティと使用料金軽減に貢献しました。
- 各デバイスの各ブラウザでテストケースを作成し結合テストを行い動作保証に貢献しました。
- 開発
- サポート期限が切れる前にリリースが完了しました。リリース後は問い合わせもなく、Webビデオ通話機能を安定的に動作させる事に貢献しました。オプション機能としての販売も継続して行えています。
**【振り返ってどう思うか・学んだ点】**
あまり使用頻度の少ないコミュニティのライブラリ等を使うと負債に繋がると思いました。
公式のライブラリで機能を作る事が大事だと学びました。
ドキュメントを読み込まないと知らないうちにアンチパターンで実装、重複料金が発生し損失に繋がるので気を付けたいと思いました。
有名なライブラリにも自分達が開発するサービスと同じで不具合がある事を学びました。