👻

旅行サービスのDXを支えるBackendの技術

2024/05/22に公開

はじめに

こんにちはバックエンドエンジニアの木村です。

今回は、NEWT 2nd ANNIVERSARY CALENDAR DAY17として、書かせていただきます。

このブログでは複雑なデータモデルや大量のデータを扱う旅行サービスにおいて、私たちバックエンドチームが取り組んでいることをご紹介します。

旅行サービスのDXに取り組む理由

海外旅行のツアーを販売・手配するには、多くの人手が介在しています。

ツアーを販売するために必要な情報が複雑かつ膨大であり、カスタマーが予約する際の手間も非常に多いです。私たちはこういった問題をテクノロジーで解決し、“ おトク ” で最適な旅行の提案や、驚くほど ” かんたん ” に予約できる『あたらしい旅行体験』を提供できるよう、日々開発に取り組んでいます。

私たちの取り組む旅行サービスのDXとは

私たちはNEWTで海外ツアーを販売しています。海外ツアーを構成する要素は以下3つです。

  • フライト
  • ホテル
  • アクティビティや送迎、保険などのオプション

これら3つを組み合わせ、魅力的なツアーを企画し、NEWTで販売しています。

しかし、これらを構成するための情報登録は簡単ではありません。ホテルやフライトの価格は日々変動するものであり、在庫も日付単位で持たなくてはなりません。また、一つのフライトやホテルに対して複数のグレードが存在し、旅行者の人数(大人・子供)まで考慮したツアーの提案ができる必要があります。

そのため、NEWTで新しいツアーを販売するためには、大量のデータ登録が必要になります。こういった運用業務の自動化にバックエンドチームは取り組んでいます。

また、私たちが工夫するのは情報の登録だけではありません。NEWTは、UXにこだわったサービスです。カスタマーに必要な情報を速く必要なだけ届ける必要があります。複雑で大量のデータを効果的に処理し、カスタマーにとってわかりやすい構造に変換してアウトプットするということにも取り組んでいます。

このような、運用業務の自動化やカスタマーに価値を届けるための情報処理において、業界をリードするような成果をあげることが、バックエンドチームの大きなミッションの一つとなっています。

Backend技術の選定

バックエンドチームが管轄する主な開発業務は以下になります。

  • (カスタマー向け)NEWTのAPIサーバ
  • (社内向け)ツアー入稿・予約管理システム(Webフロントエンド、API)

技術選定の詳細については、以前ロドリゴが書いたブログをご参照ください。

NEWT: Back-end Technology Selection

本ブログに関連することとしては、以下特徴があります。

  • 管理システムのWebアプリケーション(Next.js/TypeScript)もバックエンドチームで開発していること
  • APIの開発言語はTypescriptを採用しており、GraphQLでAPIを提供していること

NEWTと管理システム

バックエンドチームは、カスタマー向けのNEWTと運用業務用の管理システムのAPIを開発しています。エンドポイントは分けていますが、DBは共通でソースコードも同じレポジトリで管理しています。

NEWTでツアー販売に関する新しい機能を追加する場合、一人のエンジニアがNEWTと管理システム両方のAPIを改修する方が効率的なため、このようなやり方を採用しています。この開発方法を実現するためのモノレポでのエンドポイントの分け方やディレクトリ構成について紹介します。

アプリケーションコードは、旅行を構成する論理的な要素ごとにディレクトリを分けています。例えば、フライトについて扱うair、ホテルについて扱うhotel、それらを組み合わせたtourといったようにディレクトリーを分けています。

└── /modules
    ├── /air
    ├── /hotel
    └── /tour

これらmoduleの中をさらに以下のようにディレクトリ分けしています。

└── [module]
    ├── /entities 
    │   └── [entity].entity.ts
    ├── /graphql 
    │   ├── /private
    │   ├── /public
    │   └── /shared
    ├── /jobs
    └── /utils 
  • entities
    • Entityを定義するディレクトリです。TypeORMを使っており、DBのテーブルの更新は全てTypeORMのmigrationを使って実行していて、バージョン管理されています。
  • graphql
    • APIのエントリーポイントとなるGraphQLスキーマを定義するディレクトリです。NEWT用のpublicと管理システム用のprivateに分けて定義することで、コードベースを分けています。
    • NEWT用のサーバではpublicとshared、管理システム用のサーバーではprivateとsharedのresolverファイルを読み込んでサーバを起動します。これにより、エンドポイントと対応するGraphQLスキーマを分けています。
  • jobs
    • 業務ロジックが実装されるディレクトリです。
  • utils
    • 純粋関数が実装されるディレクトリです。

このようなディレクトリ構成にすることで、モジュールごとにロジックを集約しつつ、エンドポイントを分けることを実現しています。

Entityは共通ですが、publicとprivateでreturnするオブジェクト構造が違うことが重要です。

同じツアーという情報でも、ツアーを作成・管理するためのエンドポイントと、ツアーを予約するためのエンドポイントでは必要な情報が変わります。GraphQLはクライアント側で必要な情報だけfetchすることができますが、それでも不要な情報がSchemaに現れてしまうとAPIの複雑性が増してしまいます。

管理システム(Webアプリケーション)の開発

バックエンドのAPI開発には、複雑なビジネスロジックの理解が必要不可欠です。バックエンドエンジニアは、管理システムを使用する社内のメンバーと会話して複雑なビジネスロジックを理解し、API開発に落とし込んでいきます。

複雑なビジネスロジックや運用フローが直接現れやすい管理システムのフロントエンド開発も、バックエンドエンジニアが行う方が効率が良いのです。
バックエンドエンジニアがフロントエンド開発を行いやすいように以下を採用しています。

  • 言語はTypeScript
    • 言語もエディタもバックエンドと共通のためスイッチングコストが低くなります。
  • デザインシステムはAnt Design
    • あらゆるタイプのUIに対応するコンポーネントが提供されるため、簡単にフォームを作成することができます。カスマター向けではないため、NEWTほどデザイン性が求められない管理システムの開発においては、共通化されたシンプルなコンポーネント集は非常に便利です。

運用業務の自動化・効率化

ツアーを構成する情報は複雑です。ホテルとフライト、それぞれにおいて日ごとの在庫や価格の管理をする必要があります。また、その管理する単位も部屋の種類やグレード、フライトのクラスなど多岐にわたります。

こういった情報を登録する際にも、ホテルや航空会社から受け取る在庫・価格表のフォーマットが統一されていないため、どうしても人手が必要になってしまいます。

私たちの管理システムも、リリース速度を優先するために最初はスプレッドシートから情報を取り込むような仕様になっていました。ですが、NEWTをリリースして2年、ツアー入稿は80%の作業時間削減に成功しました。

自動化・効率化の手段は主に二つです。

自社で完結するもの

  • OCRを使ったパスポートの読み取り
    • OCRを使ってパスポート情報を読み取ることで、カスタマーの入力ミスによる運用業務を削減しました。
  • 旅行者名(日本人)の入力誤りチェック(この開発の詳細はこちら)
    • 機械学習したモデルで日本人の名前のたしからしさをチェックすることで、カスタマーの入力ミスによる運用業務を削減しました。
  • 旅程表自動作成機能
    • NEWTで表示される旅程表を自動で作成します。

外部連携するもの

  • フライト・ホテルの在庫・価格登録の自動化
    • 外部サービスと連携することで、スプレッドシートで入稿していた在庫・価格登録を一部自動化しました。在庫や価格をなるべくリアルタイムで連携するために、スケジューラーやキューイングを使って効率的に外部サービスの情報を取り込むシステムを開発しました。

未来展望と課題

NEWTがリリースされて2年、多くのカスタマーに利用いただきサービスが大きくなりました。その中でシステムも拡大・複雑化し、各メンバーがシステム全体を理解するには限界を迎えている状態です。しかし、まだまだ実現したい機能や挑戦したいことがたくさんあります。

システムが複雑化・巨大化しても開発品質と速度を損なわいようにするためのチームやシステムの移行が必要となります。例えばツアーを構成する複雑なデータモデルのうち、在庫管理や価格計算を隠蔽することができればカスタマー向けエンドポイントの開発生産性を上げられるかもしれません。

今期私たちはバックエンドチームという大きな横軸と、価値提供の種類という縦軸とでマトリクス上にチームが別れます。こういった組織的な切り分けを軸に、開発するシステムも組織の境界に近いところで疎結合にするための取り組みをやっていきたいと考えています。

このような取り組みを実現することで、プロダクトやチームをさらにスケールさせていきたいと考えています。

令和トラベル Tech Blog

Discussion