LINE株式会社は、2023年10月1日にLINEヤフー株式会社になりました。LINEヤフー株式会社の新しいブログはこちらです。 LINEヤフー Tech Blog

Blog


LINEドクターフロントエンド開発の流れ

こんにちは。LINEフロントエンド開発センターのYoungjin Jangです。

この記事ではオンライン診療サービスLINEドクターの概要と、フロントエンド開発の流れについて紹介します。LINEドクターは2020年リリースし、医師と患者の距離を縮めることを目指してサービスを展開しています。

多くのユーザーのコミュニケーションを支えるLINEだからこそできるオンライン診療サービスの特徴と、その開発の様子を、この機会に是非知っていただければと思います。

こちらがLINEドクターの入口となる画面です。ここからエンドユーザーはオンライン診療を申し込んだり、薬の配送を申し込んだりします。オンライン診療の予約が確定すると、ユーザーはLINEでのビデオ通話を使って診療を受けます。予約し、受診し、薬を受け取るまでをLINEを通して完結することができるサービスです。

LINEドクターのフロントエンド開発は、概ね下記のような流れになります。バージョンごとに企画からデプロイまでをワンサイクルで開発します。各段階でフロントエンドエンジニアが何をしているのか、今からお話しします。

企画・デザイン

新規機能についてはまず企画組織で定義し、デザイン組織でUIデザインの検討などが行われます。その後、フロントエンドエンジニアは新規機能について技術的な調査と検証をします。主に、新規機能が現在の技術で実装できるか判断したり、難しい場合は検証後、提供が可能かなどを判断します。また、実現可能性の検証に加えてより良いUX(User Experience、ユーザー経験)を提供できるかなども検討しています。

LINEドクターでは、オンライン診療を申し込む際に身近な病院を探せるよう位置情報を利用しています。下記は、位置情報取得許可のポップアップに対するUX改善の事例です。検証によってブラウザーのポップアップの有無を区分する方法を見つけ、不要なポップアップの表示を削除することができました。このように検証をして、改善ができるかを検討します。

UX改善前
UX改善後

提案された全ての仕様を開発して提供することが一番良いと思います。しかし、リソースは限定的なので、案件の優先度とリソースを考慮し、今回のバージョンに入れる仕様を決めます。今回のバージョンに入れる仕様が決まったら、Jiraを利用して、開発案件のチケットを作成します。

下記は以前作成したチケットの一部です。

設計

チケットの作成が終わったら、設計をします。設計は、概ねフロー、URL、UIについてしています。フロー、URL、UI設計以外にもシーケンス図や、コンポーネントのインターフェース設計など開発する前に整理が必要であればなんでも設計をしています。全ての案件に対して設計をしているわけではありません。簡単なタスクは設計をスキップする場合もあります。

まずフローの設計についてです。フローの設計は仕様を実装する際、どんな流れになるかを描いてみることです。フローの設計をすることで仕様をより明確に把握することができますし、詳細なタスクを把握することができます。また、仕様で見逃したUXの改善部分を事前に見つけることもできます。

フローの設計の際には各画面のデータ管理も設計しています。たとえば、A画面からB画面に遷移する際、A画面にあるデータをB画面にどのように渡すのか?です。データを保存する方法はメモリー、ブラウザーのストレージ、URLのパス引数、データベースなどがあると思います。個人情報のデータか、臨時データかなどを考えて設計をしています。

LINEドクターでは、予約時に、次のような流れで診療情報を入力しています

  1. 対象患者、個人情報入力
  2. 保険証登録
  3. 医療証登録
  4. お支払い方法選択
  5. 問診票入力
  6. 医療機関確認
  7. 受付内容確認

下記はそのフローの設計です。

次にURLの設計についてです。まず、画面にURLを付与するかどうかから考えます。直接アクセス可能な画面かを考えて、URLの付与可否を判断します。例えば、外部サイトから画面に遷移する場合、URLを付与します。現時点で、直接アクセスするところがなくても、拡張性を考慮して今後可能性が高いと判断する場合は、URLを付与します。

URLを付与することになったら、URLのパス、引数などを設計します。URLもユーザーの立場ではテキストUIだと考えて、ユーザーが読む際、どんなページか想像できる名前を使います。

下記はLINEドクターのクリニック検索画面のURL設計です。クリニック検索画面はLINEドクターのLINE公式アカウントのリッチメニューからアクセスが必要なのでURLを付与しました。ユーザーがURLを見ただけで"クリニックを検索する"を想像できるように、URLは"/clinic/search"にしました。

最後にUIの設計についてです。UIの設計はTop-Down方式でしています。

LINEドクターはモバイルのみで提供しているので、デスクトップのように複雑なUIはありませんでした。なので、Bottom-Up方式のコンポーネントをできるだけ小さく分けて設計するよりは、Top-Down方式の大きな画面を先に設計し、必要に応じて小さなコンポーネントを設計する方法が最適だったので、この方法を選択しました。

たとえば、このような方法で進めています。まず、ページを大きなコンポーネントとして作成します。そして、ページ内やページ間で共通のUIが使用される場合、該当UIを小さなコンポーネントとして作成します。

下記はLINEドクターのクリニック詳細画面と、スケジュール選択画面のUI設計資料です。2つのページを大きなコンポーネントとして作成し、共通して使用されるクリニックの情報UIを小さなコンポーネントとして作成しました。そして、クリニック詳細画面内で、共通して使用されるUIもコンポーネントとして作成しました。

コード作成

設計まで完了したら、実際にコードを作成しながら、UIを作ります。

コードを作成する際、APIと連携する必要がある場合はAPI開発者にダミーデータをレスポンスするAPIの開発を頼んだり、MSW(Mock Service Worker)のようなツールを利用して作業する場合があると思います。LINEドクターも最初はこの方法で作業を進めました。

しかし、この方法はAPI開発完了を待たずに開発を進めることはできますが、

  • APIレスポンスの値によってUIが変わる場合、APIレスポンスの値を手動で変えながら作業をしなければならない
  • APIの開発完了後実際のAPIに変更するため二重に作業しなければならない

というような、生産性が落ちる問題がありました。

なので、ダミーデータはテストコードに定義して、テストコードを書きながら作業すれば良いのではないかと考えました。LINEドクターはテストツールとしてCypressを利用しているので、Cypress.intercept APIがこれを実行するのにぴったりでした。

APIレスポンスの値を手動で変えながら作業したものは、すべてテストケースで作成してCypressの動作を見ながら作業することにしました。そして、Cypress.intercept APIは実際のコードに影響がないので、API開発完了後に追加処理しなければならない部分もなくなりました。

それにより、API開発者とインターフェース議論のみ行い、以降はそれぞれ作業を進めてAPI開発とフロントの開発がほぼ同時に完了するようになりました。さらに、不要な作業を無くし、生産性も上がりました。

下記のようにテストコードを作成しながら作業し、

it('予約済みの場合、「予約完了」バッジを表示する。', () => {
  cy.intercept('GET', '/api/treatments/*', {
    status: "RESERVED"
  });
  cy.visit('/treatments/123');
  cy.get('[data-testid="treatment_status"]').should('contain', `予約完了`);
});
 
it('診療完了の場合、「診療完了」バッジを表示する。', () => {
  cy.intercept('GET', '/api/treatments/*', {
    status: "DONE"
  });
  cy.visit('/treatments/123');
  cy.get('[data-testid="treatment_status"]').should('contain', `診療完了`);
});​

動作は下記のようにCypressを見ながら確認しています。

コード作成後にはコードレビューをします。コードレビューはGithubのプルリクエストを利用しています。プルリクエストのコードは修正によって発生するバグを防ぐためにDrone CIを連携し、全てのコードのリグレーションテストをしています。LINEドクターのテストケースは1000個以上あるので、リグレーションテストを実行する際には時間短縮のため、Cypressを並列して実行しています。

下記はCypressを並列処理する際のDrone CI設定です。

...
 
steps:
  - name: build
    image: node:12.22.12
    commands:
      - npm install
      - npm run build
 
  - name: test1
    image: cypress/base:12.22.8
    commands:
      - npm run start & $(npm bin)/wait-on http://localhost
      - npm run cypress:run -- --spec='pages/foo/*.cy.js'
    depends_on:
      - build
 
  - name: test2
    image: cypress/base:12.22.8
    commands:
      - npm run start & $(npm bin)/wait-on http://localhost
      - npm run cypress:run -- --spec='pages/bar/*.cy.js'
    depends_on:
      - build
 
...

下記は実際開発した案件のプルリクエストと、そのプルリクエストのコードに対してリグレーションテストをしている図です。

QA(Quality Assurance、品質保証)

コードを作成してベータ環境に反映したら、サニティテスト(Sanity Test)をします。サニティテストの項目はQAエンジニアが作成し、フロントエンドエンジニアがブラウザーで触りながら確認します。

下記はLINEドクターのサニティテストの項目の管理画面です。このように項目を確認してPassまたはFailの結果を入れています。

サニティテストが終わったら、QAエンジニアが様々なデバイスでテストをします。バグが登録されたらバグの修正と、該当バグのケースをテストケースに入れています。

QA期間に様々な状況で作られたテストコードは、今後リグレーションテストをする時に役立ちます。

デプロイ

QAまで完了したら、社内システムを利用してデプロイをしています。デプロイは概ね下記のような流れです。

デプロイはサイクルの中で一番簡単ですが、ミスが発生すると大きな障害になるので、一番集中して作業をしています。ミスを防ぐためにSlack通知やデプロイ開始の報告をしてからデプロイすることなどを徹底しています。

下記はデプロイする際送信しているSlack通知の1つです。Jenkinsでビルドを実行する際に、どのコードをデプロイしているかのSlack通知です。通知を見て、誤ったコードをデプロイしている場合すぐに中止しています。

デプロイ完了後Sentryを利用してエラーのモニタリングをします。問題がなければ、これでデプロイ作業は終了になります。最後にGithubにリリースタグを作成すると、開発のワンサイクルが終わります。

下記は実際に作成したリリースタグの1つです。

まとめ

ここまで企画からデプロイまでのLINEドクターのフロントエンド開発の流れについて紹介しました。

私たちは下記の点に重点を置いて開発しています。

  • 研究してより良いUXを目指す
  • コードを書く前に設計をする
  • テストコードを活用して、様々な問題を解決する
  • QAを機会にテストコードを強化する
  • デプロイの際はミスを防ぐ方法を考える

まだ、たくさんの改善すべき部分が存在していると思います。今後改善しながら私たちの経験を共有したいと思います。

ここまで読んでいただき、ありがとうございました。

UIT 新春 Tech blog 2023記事一覧

1. Git submoduleを使ってマルチリポジトリなMonorepoを管理する
2. LINEドクターフロントエンド開発の流れ
3. 静的リソースをCDN配信する社内サービス『Abyss』のフロントエンドを作り直した話
4. LINE NEWS フロントエンドの自動テストの改善