Medley Developer Blog

株式会社メドレーのエンジニア・デザイナーによるブログです

メドレー知財担当がエンジニア・デザイナー向け社内勉強会で"特許"について発表しました

  • はじめに

こんにちは、メドレーのコーポレート本部法務コンプライアンス部で知的財産関連の業務を担当している鬼鞍です。コーポレート本部といっても、知財担当の仕事内容としてはエンジニア、デザイナーの方々としっかり協働することが一番大事なので、テックブログにも僭越ながら登場させていただきました。

 

先日、社内勉強会のテックランチにて、「特許」についてお話しする機会がありました。

今回の勉強会は、コロナウイルスの影響で全員オンライン参加という状況下でうまく伝えられるか心配だったのですが、予想以上に質問を頂いてそれなりに反響がありましたので、ここで紹介させていただこうと思います(厳密には特許権のことですがここでは説明の便宜上、以下特許と称することにします)。

 

みなさん、特許と聞いてどのようなイメージをもたれるでしょうか? 

 

あなたが知財を仕事にしている人ではない限り、多くの方にとっては馴染みの薄い世界かもしれません。今回は、世間ではあまり表に出てこない特許という世界にスポットライトを当てつつ、少しでも特許の面白さみたいなものをお伝えできればと思います。

 

  • 特許とは陣地に敷かれた地雷でもあり、身を守る鎧でもある

さて、秒で特許のイメージをつかんでいただくためにここでは極端な例えをします。

 

他人が取得した特許は陣地に置かれた地雷のようなものであり、この地雷を踏んでしまうと特許権侵害というリスクで怪我をしてしまいます。あまりいい例えではないかもしれませんが、これは特許が技術を独占的に実施し、他社が実施した場合には排他できるという側面を表現しています。

企業の知財部門は、地雷を踏まないように日々特許調査をし、地雷のない安全な道を探る、いわば道先案内人のようなものなのです。

また逆に、自分たちが取得した特許があれば、地雷を踏んで権利を主張されてもカウンターパンチを当てることができるので、身を守るための鎧にもなるわけです。

f:id:medley_inc:20200522160511j:plain

 

  • 特許とはエンジニア、デザイナーの成果物である

ここで、特許について少し目線を変えて見てみましょう。

特許というものは、皆さんが努力・工夫した目に見えない技術的なアイディアが見える化された成果物である、という見方もできます。皆さんの頭の中にあるアイディアに知的財産権という形を与えることで、外部の人たちに明確に示すことができます。これによって、例えば投資家から高い評価を得たり、自分たちの技術力をPRするためのツールとして特許を用いることもできるのです。

f:id:medley_inc:20200522152632j:plain

 

  • 特許権は国から与えられるグッドアイディア賞みたいなもの

特許については知らなくてもグッドデザイン賞についてはご存知の方が多いかもしれません。


メドレーのプロダクトであるクラウド診療システム「CLINICS」はグッドデザイン賞を受賞しています。

クラウド診療支援システム [CLINICS] | 受賞対象一覧 | Good Design Award

また、ISMS情報セキュリティマネジメントシステム)についての認証も受けています。

全社で本気になってリーンにISMSの仕組みをつくった話

 

なぜ、こんな話をしているかというと、グッドデザイン賞ISMS特許権も1つの共通点があるからです。それはいずれも客観的な審査を経て合格したものにだけ与えられてるものだという点です。

そして合格したものは、対外的に一定の信用を示すことができる、という機能を備えていいます。日本の特許庁の審査レベルは世界的に見ても高水準であると言われています。特許権というのは、その企業が技術的なアイディアに優れているという一定の信用を示すためのツールとしての性質も兼ね備えているのです。

 

  • 特許に潜むリスク

先ほど特許は地雷であるという話をしました。より具体的に地雷を踏むとどんなリスクがあるのでしょうか?そのリスクは主に差し止め請求や損害賠償です。仮にこのような請求を受けてしまった場合は、大変な労力とコストが伴います。訴訟まで発展してしまうと、周囲の信用を失うことにもなりかねません。

このようなリスクを最小限にするために、知財担当の私が各プロダクトごとの開発定例に同席して自社の開発動向をキャッチアップし、他社権利の特許調査を行っています。

f:id:medley_inc:20200522152754j:plain

 

  • 特許的な思考プロセスとは本質を考えること

さて、ここで「特許的な思考プロセス」を使って皆さんに少し頭の体操をしていただこうと思います。

 

知財関連ではよく例に取り上げられるのですが、鉛筆の発明を題材にして考えてみます。

 

あなたは断面が円形の鉛筆を使っていましたが、机の上を転がって下へ落ちてしまうという問題点に気がつきました。あなたは、鉛筆の断面形状に着目し、断面を五角形にすることにより、この問題を解決したとしましょう。そして、「断面が五角形の鉛筆」という内容を特許請求の範囲(特許権の権利範囲部分を決めるもの)に記載して特許権を得ることができたとします。

f:id:medley_inc:20200522152846j:plain

 

しかし、その後、あなたの断面五角形の鉛筆を見て他の業者が断面を三角形や四角形にした鉛筆を思いつき、それが市場に多く流通し、あなたの断面五角形の鉛筆の売り上げが下がってしまいました。あなたは特許請求の範囲に何と記載すべきだったのでしょうか?

f:id:medley_inc:20200522152924j:plain

 

そう、あなたは「断面が五角形の鉛筆」ではなく「断面が多角形の鉛筆」と書いていれば良かったのですね。

そうすれば、三角形や四角形などの類似品の流通を防ぐことができました。これは簡単です。

その後、あなたは断面が楕円形でも、机の上を転がりにくいという効果を生み出すことに気がつきます。では、多角形も楕円形も含めるためにはどのような表現がいいのでしょうか?ちょっと考えてみてください。

f:id:medley_inc:20200522153019j:plain

あくまで答えの一例ですが、「断面が非円形の鉛筆」とか、「断面がその中心からの距離である長軸と短軸とを有する鉛筆」などの表現であれば上記の全ての形状をカバーすることができます。

 

このように、いくつかの具体例から、効果を生み出すために必要最低限な要素は何なのか、共通点は何なのかを探し出すことが、アイディアの本質を捉えることになります。具体と抽象の間を行ったり来たりするプロセスです。

 

アイディアの本質を捉えるためには多くの具体例を出す発想力が必要です。

もしあなたが発想力豊かなエンジニアやデザイナーであれば強力な特許権が取得できるかもしれません。実際にプロダクトに生かされていない技術的なアイディアというのはあなたの頭の中に埋もれていることが多いものです。

 

  • エンジニアやデザイナーの成果が報われる土壌作りに貢献したい

知的財産権の生みの親はエンジニアやデザイナーの皆さんです。皆さんはあまり意識していないかもしれませんが、技術的なアイディアは日々の開発業務で生み出されていて、それが形になるものもあればならないものもあります。

 

メドレーでは、これまで検討された技術アイディアのうち、プロダクトとして実現化されたものや、そうでないものにかかわらず将来性を見込めそうなものについては、実際に特許出願をしてきました。

ブロックチェーンを用いた電子処方箋の管理方法(特願2018-078928

症状チェッカー(特願2017-011444

・患者統合基盤(特願2019-233247)(出願中につき概念図をIR資料より抜粋)

f:id:medley_inc:20200522153158j:plain

 

また、メドレーでは、エンジニア、デザイナーの方々の成果物がプロダクトだけでなく、知的財産としてもきちんと社内外で認められ、それが名誉となるような土壌作りをしていこうと考えています。

 

  • さいごに

メドレーは、テクノロジーを使って医療分野のデジタル化を推進し、医療ヘルスケアの未来をつくる会社です。そんなメドレーで生み出される素晴らしい技術やデザインを知的財産という分野で可能な限りバックアップしてきたいと思っています。少しでも特許の世界を感じて頂ければ幸いです。最後までお付き合い頂きありがとうございました!

Kotlin/Native を検証してみた

こんにちは、インキュベーション本部でエンジニアをしています世嘉良です。

インキュベーション本部は2020年2月から新規事業の開拓などを目的に新設されたのですが、その中でも若手の部類として日々頑張っています。 CTO 平山のインタビューとともにインキュベーションチームの紹介記事が、コーポレートサイトに掲載されています。こちらもぜひご覧ください。 https://www.medley.jp/team/creator-story-incubation.html

さて、今回は社内で行っている勉強会:テックランチの中で「Kotlin/Native」について発表する機会があったので紹介させていただきます。

Kotlin/Native について

Kotlin は JetBrains 社によって 2011 年に発表されたプログラミング言語です。

現在では Android 開発などで主流の言語となっており、多くの人に利用されていると思います。 Kotlin/Native とはそんな Kotlin を使って様々なプラットフォーム上で実行可能なファイルを生成しようというプロジェクトです。

Kotlin/Native - Kotlin Programming Language

仕組みとしては Kotlin のコードをもとに LLVM を生成し、それを様々なプラットフォームで利用可能なネイティブバイナリにコンパイルすることで追加のランタイムや JVM なしで動作するようにしています。

サポートしているプラットフォームは下記のとおりです。

コードの共通化について

Kotlin/Native のチュートリアルを参考に、Android / iOS で共通化の流れを追ってみます。

作成されるプロジェクトは Android / iOS でそれぞれ "Hello, World!" を出力するシンプルなプログラムです。

Kotlin Playground: Edit, Run, Share Kotlin Code Online

通常のプロジェクトとは別に SharedCode というプロジェクトを作成し、この中に Kotlin/Native (Android / iOS 共通のコード) を記述していきます。 それぞれのコードのレイアウトは以下の通りです。 ※ SharedCode を読み込むためのマルチプラットフォームのための gradle ファイルも必要で、先程のウェブサイトに記載されています。

f:id:medley_inc:20200508170713p:plain

commonMain の中に 「expect」 というキーワードを使って抽象型のようなものを宣言し、 androidMain / iOSMain といった各プラットフォームの実装の中で 「actual」 というキーワードを使用してその内容を記述します。

// commonMain
expect fun platformName(): String

// androidMain
actual fun platformName(): String {
    return "Android"
}

// iOSMain
actual fun platformName(): String {
    return UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion
}

このチュートリアルには記載ありませんが、「expect」 というキーワードはクラスや関数・アノテーションといったすべてのものに定義することができます。

Platform-Specific Declarations - Kotlin Programming Language

また iOSMain 内であれば iOS の Foundation フレームワークといったように、各プラットフォームごとのフレームワークもそれぞれ利用することができます。

こうしてできた、SharedCode のライブラリは Android/iOS のプロジェクトから使い慣れたライブラリと同じようにインポートすることができます。

f:id:medley_inc:20200508170931p:plain

f:id:medley_inc:20200508170949p:plain

f:id:medley_inc:20200508171007p:plain

Kotlin/Native の制約について

JVM 上で Kotlin を動かしていた時には標準ライブラリやメモリ管理には Java の資産を利用することができましたが、Kotlin/Native ではそれを利用することができないという制約があります。

具体的にアプリを作成する際には下記の点に注意が必要でした。

  • Java の標準ライブラリを使用しているライブラリを利用できないため Kotlin で記述されたライブラリのみが使用する
  • iOS アプリを開発する際には memScope, alloc / free などを利用してメモリ管理を自分で行う必要がある

Java の資産が利用できない Kotlin に対して心配することもありましたが、Kotlin/Native 向けに様々なライブラリが 提供されておりそれらを利用することで問題を解決しました。

f:id:medley_inc:20200508171035p:plain

現状は日付管理ですらサードパーティ製のライブラリで操作する必要があるのが不満ですが、Kotlin/Native の発展によってこういった不便さは解決されるように願っています。

  • 「suspend」 関数を iOS 側から直接呼び出すことができない (コールバック関数やなどに変換して呼び出す必要がある)
  • Kotlin で定義した宣言や型の一部が Swift だと別名になっている (「 objc_runtime_name」 や 「swift_name」 を参照する必要がある)
  • 「companion object」 や 「object」 などシングルトンの宣言に対してオブジェクトをフリーズするか 「ThreadLocal / SharedImmutable」 のアノテーションを付与する必要がある

こちらは iOS で利用する場合の注意ですが、いくつかの Kotlin の機能が利用できなかったり、追加の記述が必要なものがあります。 詳しくは下記の資料を参照ください。

Kotlin/Native as an Apple Framework - Kotlin Programming Language

kotlin-native/IMMUTABILITY.md

Kotlin/Native の利用例

まだまだ利用例が少ないため参考になる資料などがあまりないのですが、以下の実装がオープンソースとして公開されているため構成や雰囲気を掴むためにはちょうど良い資料となりました。

まとめ

弊社では 「CLINICS」 というオンライン診察を行うことができるアプリをリリースしています。

CLINICS を長期的に運用していくための技術調査の一環として、近年の Android 界隈で話題にあがっていた「Kotlin/Native」について検証し発表してみました。

まだまだ発展途上感のある技術ですが、実用性のあるプロジェクトだと思いますのでご興味のある方はぜひ一度お試しください!

社内勉強会TechLunchでジョブメドレーでのCircleCIの活用と改善について発表しました

こんにちは、メドレープロダクト開発室 エンジニアの岸田です。

先日、社内勉強会TechLunchにて、弊社の提供する医療介護分野の人材プラットフォーム「ジョブメドレー」の開発で利用しているCircleCIでのCI/CDについての取り組みを発表しましたので、紹介させていただきたいと思います。

ジョブメドレーの開発でCircleCIをどのように利用しているか

ジョブメドレーの開発では、主に次の2つをCircleCIを用いて行なっています。

デプロイに関しては、ECS環境とEC2環境への2通りのデプロイをCircleCIを利用して行なっています。

そのためCircleCIのWorkflowは「ユニットテスト・構文チェック」「EC2へのデプロイ」「ECSへのデプロイ」の3つに分かれています。

3つのWorkflowを大まかに説明させていただきます。

ユニットテスト・構文チェック

ジョブメドレーは主にサーバサイドをRuby on Rails、フロントエンドをReactを使って開発をしています。 そのためユニットテストにはRSpec・Jestを、構文チェックにはRubocopとESLint利用しています。

このWorkflowは3つのジョブで構成されています。

  1. ライブラリのインストール
    • bundle installyarn installなどを行い、ユニットテスト・構文チェックの実行に必要な依存ライブラリをインストールし、CircleCIのキャッシュ機能を用いてキャッシュを行なっています
  2. RSpecの実行
    • 2コンテナを利用しての並列実行を行なっています
  3. 構文チェックとJestの実行
    • RSpecと比較してJestでのテストコードはボリュームが少なく・実行時間が短いため、構文チェックと一緒に1つのジョブにしています

f:id:medley_inc:20200430190805p:plain

このWorkflowはどのブランチでもGitHubへPushが行われるたびに実行されるようにしています。

EC2へのデプロイ

このWorkflowではデプロイを行うための準備と、文字通りEC2へのデプロイを行なっています。 デプロイにはRuby gemのCapistranoを利用しています。

下記のような2つのジョブで構成しています。

  1. ライブラリのインストール
  2. ビルドとデプロイ
    • Railsのassets:precompileやyarn buildなどの処理と、Capistranoを用いたデプロイを行なっています

f:id:medley_inc:20200430190826p:plain

このWorkflowは特定のブランチでしか実行されないようになっています。

ECSへのデプロイ

このWorkflowではECSへデプロイするためのDocker image作成とそのためのビルドなどを行なっています。

ジョブは下記のように4つで構成されています。

  1. npm packageのインストール
  2. フロントエンドのビルド
  3. GemのインストールとRailsのassets:precompile
  4. Docker imageの作成とPush

f:id:medley_inc:20200430190429p:plain

こちらのWorkflowも特定のブランチでしか実行されないようになっています。

抱えていた課題とassets:precompile

ジョブメドレーの開発ではCircleCIの各ジョブが全て正常に完了することをPRをマージする条件の1つにしています。 しかし各Workflow・ジョブの実行時間が長く、ジョブの実行待ちをしなければいけないという状況がよく起こってしまっていました。

特に時間がかかっていたのが、下記の3つでした。

  1. 「EC2へのデプロイ」Workflowの「デプロイ」ジョブ
  2. 「ECSへのデプロイ」Workflowの「GemのインストールとRailsのasset_precompile」ジョブ
  3. RSpecの実行」ジョブ
    • RSpecの書き方などを改善することで短縮できるため、割愛させていただきます

これらについて調査したところ、1・2は、assets:precompileが主に時間を使っていることが分かりました。 この点について原因と行なった改善を説明をさせていただこうと思います。

assets:precompileに時間がかかる

ジョブメドレーではRailsのアセットパイプラインを利用して、アセットファイルのコンパイル・最小化などを行なっています。 これを実行する際に assets:precompile コマンドを利用しています。 また、同コマンド実行時にコンパイルしたファイルをAWS S3バケットにアップロードするために asset_sync gemを利用しています。

このコマンドの実行には9分から10分ほどの時間がかかっており、下記の2つの原因で遅くなっていました。

  1. 毎回1からコンパイルを行なっていた
  2. コンパイル後のファイルをアップロードするS3バケットに大量のファイルが存在する

毎回1からコンパイルを行なっていた

こちらについては読んで字のごとくですが、デプロイWorkflowが実行されるたびにアセットファイルの変更有無に関わらず、毎回3分ほどを費やして全てのアセットファイルをコンパイル・最小化していました。 こちらの解決策としては、CircleCIの公式ドキュメントでも例が載せられていますが、 assets:precompile コマンドで生成されるファイルが置かれるディレクトリ(public/assets)をCircleCIでキャッシュさせることで対応しました。 キャッシュさせることで、毎回3分ほどかかっていた処理を1分ほどに短縮することができました。

コンパイル後のファイルをアップロードするS3バケットに大量のファイルが存在する

こちらついてはもう少し背景が複雑かつ、まだ解決まではできていません。

まず asset_sync を利用したファイルのアップロード処理ですが、毎回6分以上の時間がかかっていました。 CircleCIのログをよくよく見てみるとアップロード自体に時間がかかっているのではなく、「どのファイルをアップロードすべきか」を判断する処理に多くの時間を費やしていることが分かりました。

f:id:medley_inc:20200430190719p:plain

(1ファイルもアップロードしていないが6分20秒かかっている)

そこで、asset_sync gemのソースコードを読んでみると、「アップロード先のS3バケットにあるファイルを全て取得し、 assets:precompile コマンドが生成したファイルのファイル名と比較する」という処理がありました。 この処理が怪しいのではないかと思い、S3バケットを確認してみたところ数十万件以上のファイルが存在することが分かりました。

数十万件以上のファイルの情報を取得していることを考えると6分以上時間がかかるのも納得です。

この問題の解決策は下記の2つが考え得ると考えました。

  1. 不要なファイルをS3バケットから削除する
  2. 前回のデプロイとの比較をしてS3にアクセスせずにアップロードすべきファイルかどうかを判断するようにする

1つ目の方法は正攻法で、数十万ファイルを全て使っているわけではないため利用されていないファイルを削除してしまう方法です。

asset_syncも早くなり、S3の利用料も少なくなるためこの方法を取れるのであれば、この方法で解決するのが良いように思います。 ジョブメドレーでもこの方法を取れないかと検討しましたが、ジョブメドレーから配信しているHTMLメールなどでも利用しているファイルがあるため一概にアクセスされていないからといって削除することができず、この方法での解決は一旦断念しました。

2つ目の方法はassets:precompileコマンドが生成するmanifestファイル(生成したファイルのリストなどが記述されている)とCircleCIのキャッシュ機能を使って短縮する方法です。

manifestファイルは、コンパイル後のアセットファイルが出力されるディレクトリ(public/assets/)に同じように出力され、また、上記でpublic/assetsをCircleCIのキャッシュ機能でキャッシュするようにしたため、manifestファイルも一緒にキャッシュされるようになっています。

assets:precompileの実行により今回作成されたmanifestファイルと、キャッシュされていたmanifestファイルを比較して差分が出たファイルだけをS3にアップロードするようにしようという試みです。 この処理はasset_sync gemではできそうになかったので、シェルスクリプトとRakeタスクを作成して実行してみたところ、「アップロードすべきファイルかどうか」を判断するための時間がほぼなくなり、6分以上の短縮をすることができました。

ただし検証が不十分なため、実運用に乗せることはまだできていません。

CircleCIのジョブ実行時間を短縮する小さな改善事項

上述の通り、各Workflowで大きく時間を費やしているのはassets:precompileRSpecの実行でしたが、細かな点としては他にも小さい改善をしたことがあります。

コードのチェックアウト

CircleCIでは組み込みのコマンドとして checkout コマンドがあります。 これは対象のリポジトリのブランチをクローンしてくれるコマンドですが、ジョブメドレーはモノレポに近い構成になっており、コードベースのサイズや履歴が大きいためクローンするだけである程度の時間がかかってしまっています。

そこでまずは、.gitディレクトリをCircleCIのキャッシュ機能を利用してキャッシュするようにしてみました。 すると、checkoutコマンド自体は大きく短縮しましたが、キャッシュのsave/restoreに短縮した以上の時間がかかるようになってしまいました。

別の方法としてcheckoutコマンドを利用せずに、GitのShallow cloneやSparse cloneを駆使して必要なファイルや履歴だけをクローンするということができます。 現在はSparse cloneを一部導入してみており、Shallow cloneも導入したいと考えています。

Docker imageの作成

ジョブメドレーではECSへのデプロイの際にCircleCI上でDocker imageをビルドしているため、docker buildコマンドの実行時間も可能な限り抑えたいと考えています。

短縮する方法は様々あるかと思いますが、CircleCI上でもDokcer Buildkitを利用することがきますので、それを利用してビルドすることで簡単に短縮することができます。

詳しくはDockerのガイドに記載の通りではありますが、DOCKER_BUILDKIT=1を指定してdocker buildを実行するだけで利用することができ、ジョブメドレーでは2分ほどかかっていたビルドを40秒ほど短縮することができました。

まとめ

今回は、TechLunchで発表したジョブメドレーにおけるCircleCIの活用と改善の取り組みについて紹介させていただきました。 今回紹介させていただいた以外にも様々な用途があり、今後もさらにうまく活用していきたいと思っています。

ご覧いただきありがとうございました。

社内勉強会TechLunchでCLINICSを取りまく監視ツール群について発表しました

皆様こんにちは。
プロダクト開発室 エンジニアの濱中です。

新型コロナウイルス感染症が猛威を振るっておりますが、皆様いかがお過ごしでしょうか。先日の緊急事態宣言を受けて、メドレーも全社員が原則リモートで業務に当たっています。オンライン医療事典「MEDLEY」にも、コロナウイルス関連の特集が組まれていますのでぜひご覧ください。

さて先日、社内勉強会TechLunchにて、弊社の提供するクラウド診療支援システム「CLINICS」のサービス運営で使われている監視ツール群について発表したので、ご紹介させていただきます。

CLINICSの概要と、サービスにおける監視の立ち位置について

公式ページで「クラウド診療支援システム」と銘打っているCLINICSですが、より詳細には、電子カルテシステム・オンライン予約システムも提供しています。これら予約・診療・カルテの3プロダクトで医療現場の業務を一手に引き受けることを目的としたサービスがCLINICSです。

このうち、電子カルテシステムは、「日医標準レセプトソフト ORCA」という製品を内包する形で提供しており、ORCA自体は独立した環境で動作しています。

当然ながら、ORCA自体がCLINICSとは独立した1プロダクトであるため、CLINICS側に問題がなくてもORCAサーバがパフォーマンス低下や不具合を起こしてしまったり、あるいはCLINICSのwebサーバとの通信がうまくいかなくなるケースも考えられます。

電子カルテシステムは医療機関の診察・会計といった日常業務の重要なパートを担っており、ここで障害が発生すると業務が止まってしまいます(最悪、患者さんをお待たせしてしまうこともあります)。

そのため、業務に大きな影響を与える箇所を中心に、複数の監視ツールでアプリケーションの動作状況をチェックしています。

監視ツールあれこれ

ここからは実際にCLINICSで利用しているツールを簡潔にご紹介していきます。

Sentry

https://sentry.io/

弊社の他プロダクト(「ジョブメドレー」、「介護のほんね」)でも利用している監視ツールです。

基本的には、アプリケーションで例外が発生すると自動でアラートを投げてくれますが、アプリケーション側でcatchしてしまうものや、例外ではないが通知したいイベントについて、任意にアラートをあげることも可能です。

CLINICSでは例えばアカウントIDやアクセスしたAPIエンドポイント・パラメータなど渡して、エラー調査に活用しています。

Mackerel

https://mackerel.io/ja/

GUIで簡単に監視設定が可能なサービスです。

前職で使っていた時はGUIでできるところまでしか触っていなかったのですが、設定ファイルを手製すれば、自作スクリプトの出力をチェックしたり、チェックに失敗した時何か処理をしたり…といったマニュアルな監視も可能です。

現在CLINICSにおいては、ORCAインスタンスがそれぞれ独立して動作していますが、MackerelではこのORCAインスタンスを監視しています。また監視するだけでなく、動作不良を起こした時の再起動処理なども担当しています。

AWS CloudWatch & Lambda

https://aws.amazon.com/jp/cloudwatch/

https://aws.amazon.com/jp/lambda/

どちらもAWSの提供するツールです。

CloudWatchは主にログの記録と監視を行うためのツールです。複数の機能がありますが、CLINICSでは主にLogs, Metrics, Alarmを使用しています。

Logsはその名の通り、主にAWSのツールが発行するログを収集・検索・閲覧する機能で、問題発生時のHTTPリクエストのパラメータを確認する時などに利用しています。

Metricsは、「プロダクト(EC2ならインスタンス, RDSならDBインスタンスなど製品の一単位)」×「メトリクス種別(CPU利用率など)」を一単位として、統計情報を可視化するツールです。

それらに閾値を設け、超えた場合にアラートを発行するのがAlarm…という位置付けです。

対してLambdaは、そもそも監視ツールではありません。定期実行、あるいは何かのイベント(S3に何かアップロードされた、など)をトリガーとして、処理を行うツールです。処理した結果を、さらに別のツールへ連携(Slack通知などの外部連携も含む)させることも可能です。

CLINICSでは、上記アラート通知のほか、SessionManager経由でインスタンスsshログインした時の通知や、時間のかかるインポートタスクなどが終了した時の通知などにも利用しています。

New Relic

https://newrelic.co.jp/

New Relicは、CLINICSではパフォーマンス評価ツールとして利用しています。

メインとなるのはAPM(Application Performance Monitoring)で、アプリケーション内のどの処理にどれだけ時間がかかったかなどを閲覧することができます。

f:id:medley_inc:20200410183154p:plain

医療機関は時間によって診察ペースが大きく変わるため、1回1回は少しの遅延であっても、業務フローのコアな部分に絡んでいる場合、遅延が響いてくることはあります。

このような、「エラーは出ないけど、レスポンスが遅い」というご連絡を受けた時の調査・メンテナンスに主に活躍してくれます。

Sentryのようにエラー検知を行なったりもでき、ツール自体の多機能さから取得できる情報の多さが段違いといった印象です。

Firebase Crashlytics

https://firebase.google.com/?hl=ja

Firebaseもまた”多機能な”ツールですが、CLINICSでは監視機能としてCrashlyticsを使っています。

CLINICSでは、患者さんが予約・オンライン診療を行うためのアプリを iOS / Androidで公開しており、医療機関向けのWebアプリケーション側と連携して動作します。このネイティブアプリで発生したクラッシュを集計しているのがCrashlyticsです。

Androidの場合はbuild.gradleに設定を追記してアプリをビルド、iOSの場合はcocoapodsで外部ライブラリとしてインストールすることで集計が可能になります。Unityアプリにも対応しているとのことです。

その他、監視ではないですがアプリを利用している端末やOSバージョンなどの統計情報の収集も可能です。

PagerDutyによる監視集約

https://ja.pagerduty.com/

CLINICSではここまでに挙げてきたツールを使って監視を行っておりますが、昨年、複数の監視ソースからのアラートを一本化すべく、インシデント管理サービスPagerDutyを導入しました。

導入後は、全てのアラートツールはアラートを一旦PagerDutyに集約し、PagerDutyからSlack通知を行うという形式になりました。

 

f:id:medley_inc:20200410183430p:plain

f:id:medley_inc:20200410183455p:plain

また、PagerDutyが出すアラートは、担当者が確認してレスポンスを返す(acknowledge)ことを行わずに一定時間が過ぎた場合、電話やSMSでの通知へ展開していくように設定することができます。これによって、クリティカルなエラーの見落としを確実に防げるようになりました。

まとめ

CLINICSで利用している監視ツール+αを紹介させていただきました。

これらのツールを駆使しながら、ユーザの皆様に安心してお使いいただけるようサービスの安定稼動に尽力しています。

ご覧いただきありがとうございました。

2020年、プロダクト開発合宿に行ってきました!@伊東

こんにちは、インキュベーション本部の加藤です。 2019年に新卒でメドレーに入社し、間もなく1年が経とうとしています。

少し時間が経ってしまったのですが、今回は1月に行われたプロダクト開発合宿の様子をお届けします。

プロダクト開発合宿の目的

メドレーでは「1年間の方針を共有すること」「メンバー間の親睦を深めること」を目的とした開発合宿を、毎年年始に行っています。

合宿の恒例行事となっている「1年間のプロダクト開発の指針」をCTO平山がプレゼンし、全員で共有する大切な機会です。 また、親睦を深める観点で、集中して一気に何かを開発するような合宿ではなく、普段あまり体験しないであろうアクティビティが中心です。

アクティビティの紹介

そば打ち体験

今年の合宿のアクティビティは、そば打ち体験でした。 「チームでひとつの作業に臨むことで、普段の業務以外でのメンバー間の絆を深めてもらいたい」という理由から、そば打ちがアクティビティに選ばれました。

今回お世話になった観音亭さんは、他ではなかなか経験のできない「石臼挽き」から体験できるおそば屋さんです。

f:id:medley_inc:20200327183356j:plain

石臼挽きを終えたら、挽いたそば粉をこねて伸ばしていきます。 職人さんの説明をよく聞きながら、普段食べている蕎麦の太さになるように薄く生地を伸ばしていきます。

f:id:medley_inc:20200327183437j:plain

生地が薄くなりすぎると破れてしまうことも......!

f:id:medley_inc:20200327183459j:plain

伸ばした生地を大きな包丁で切れば、見慣れた蕎麦の形になっていきます。

f:id:medley_inc:20200327183538j:plain

自分たちで打ったそばは、少し太さにばらつきはあるものの、その場で茹でていただきとても美味しくいただくことができました。 他のメンバーもそば打ちを楽しむことができたようで、満足した様子でした。

f:id:medley_inc:20200327183616j:plain

城ヶ崎海岸を散策

そば打ち体験の後は、サスペンスドラマの撮影で使われることでも有名な城ヶ崎海岸に移動し、周辺を散策しました。 門脇吊り橋という大きな吊り橋を渡って少しスリルを味わいつつ、城ヶ崎海岸の絶景を楽しむことができました。

f:id:medley_inc:20200327183707j:plain

f:id:medley_inc:20200327183729j:plain

バーベキュー

夕方には宿泊先に到着し、バーベキューを開始! お酒を飲んだり、雑談したり…時にはプロダクトや組織について熱く語りあったりと楽しい時間を過ごすことができました。

f:id:medley_inc:20200327183804j:plain

f:id:medley_inc:20200327183823j:plain

2020年キックオフ!

バーベキューの後は CTO 平山から2020年に向けてのキックオフです。

f:id:medley_inc:20200327183849j:plain

まず、2019年の振り返りから。

昨年はメドレーにとってもプロダクトにとっても大きな変化のある1年でした。

会社としては創業10周年を迎え、東証マザーズへ上場を果たしました。
ジョブメドレーの大幅なデザインリニューアルや CLINICS のグッドデザイン・ベスト100の受賞など様々なことがあった1年でした。

続いて2020年について。
詳細は記載できず残念なのですが、なにを目指すのか、それをどう実現していくのか…CTOからのメッセージを全員で確認する良い機会となりました。

普段の業務では目の前のタスクばかりに目が向き、つい視野が狭くなってしまうため、日常や業務を離れて少し引いた目でプロダクトや開発組織のこれからについて考える時間も必要なのだと感じることができました。

まとめ

今回はメドレーのプロダクト開発合宿の様子をお届けしました。

私自身、今回初めての合宿参加でしたが、メンバーと同じ時間を過ごすことで、普段見ることのできない一面を知ることができました。 また、これからの1年について考える時間ともなり、2020年、より良い1年にしていきたいです。

最後に、今回の合宿の企画運営をしてくださった前田さん・新居さん、本当にありがとうございました!

f:id:medley_inc:20200327183919j:plain

2019年度エンジニア新卒の研修について

こんにちは。エンジニアの平木です。

メドレーでは今年度より新卒採用活動を本格化しており、今年はエンジニア4名が新卒社員として入社しました。

現在、新卒メンバーは6ヶ月の開発研修が無事終了し、各部署で業務に勤しんでいますが、このエントリでは、初めての新卒研修をどのような視点で計画・実行していったか?を書いていきたいと思います。

f:id:dev-medley:20191216115245j:plain
2019年度新卒入社メンバー

新卒研修を決めるまでやったこと

研修の大枠決定

カリキュラムの大枠を決めるため、まずCTOの平山が「こんなことをやろう」という大枠の方向性を出し、施策レベルに筆者が落としこんでいきました。

決めたことは、以下3点です。

  • 入社後の導入部分
    • 社会人としてのビジネスマナーや考え方の基礎を学ぶ
    • プロダクト開発をする上で必要になる基礎を学ぶ
    • 会社の事業内容を理解する
  • OJTをメインとした各チームへの仮配属
  • 新卒社員へのフォローアップ
    • メンターや部長との定期報告会
    • 半年後に役員陣への成果報告会

エンジニアとして価値を出していくため必要な「社会の課題を解決するために、日々自身の腕を磨き、純粋に取り組む、ただそれだけ」という、メドレーが求めるエンジニアとしての姿勢をきちんと体得してもらうことが目標です。

こちらについては平山のブログに詳しく書かれているので、ぜひご参照ください。

情報収集

社内エンジニアへのヒアリング

前職で新卒研修を受けたことがある社内の20代~30代のエンジニア4人を対象に、研修内容についてヒアリングしました。

ヒアリングしたポイントは

  • 研修の期間
  • 研修全体の流れ
  • 各研修メニューの内容
  • OJTはどういった形で受けたか
  • 研修を受けての感想

など。各社・各年代で個性が出るなという印象を持ちました。

やはり、エンジニアということで座学よりも手を動かすハンズオン形式の方が印象に残ることや、印象的な研修メニューは時間が経っても覚えているという傾向が分かりました。

ネットでの情報収集

ご存知の通り、近年では新卒研修のブログや、学習プログラムに関しては多くの企業様が書かれています。

しかし、内容としてはアプリ開発をこのような形式で行ないました」という情報が多く、研修全体や社内情勢も踏まえた背景などが書かれているものは意外に少ないなという印象を持ちました。

そんな中、各社の新卒研修エントリがGistにまとめられているのを発見しました。 こちらは大変参考になりました。作者の方にはこの場をお借りして感謝させていただきます。

研修資料まとめ.md · GitHub

研修メニュー決定

研修の詳細メニュー

ここまでの過程を踏まえ研修メニューを筆者が考え、CTOや開発部部長の田中・副部長の稲本と刷り合わせをしていきました。

結果として、以下のメニュー構成でいくことになりました。

  • オリエンテーション
    • [座学]社会人研修や会社全般の知識の習得を目的にする
  • 開発基礎研修
    • [座学]Webアプリケーション開発の基本や、エンジニアとしての心得、会社の展開するサービスの基本知識を習得することを目的にする
  • 開発実践研修
    • [OJT]社内向けにWebアプリケーションを開発し、チーム開発を実践することを目的にする
  • 開発部OJT
    • [OJT]稼動しているサービスの開発を通して、業務としての開発を実践することを目的にする
  • 事業部OJT
    • [OJT]ビジネスサイドの業務を体験し、開発以外の会社の業務の全体像を理解することを目的にする

特に事業部OJTは新卒メンバーには必ず理解してもらいたい、と決まった研修項目です。

メドレーではプロダクトファーストで開発しますが、プロダクトの機能や要望は実際のビジネスの流れと密接に関わっています。

新卒メンバーもこういった流れを把握出来ていないと、要点を押さえた開発ができません。実際にどのような流れで顧客と関わっていき、自分達が開発するプロダクトにどう影響していくかを体験してもらうために、この事業部OJTをメニューに組み込みました。

研修期間

研修の期間についても様々な意見が出ましたが、最終的には配属後の業務にスムーズに入ってもらえるように、基礎を重視して長めに研修時間を取ったほうがよいと決め、以下の通り全6ヶ月という研修期間を定めました。

  • オリエンテーション・開発基礎研修・開発実践研修
    • 2ヶ月
    • 期間中、午前:開発基礎、午後:開発実践
  • 開発部OJT・事業部OJT
    • 4ヶ月
    • 事業部OJTは期間中に2週間 x 2つの事業部で実施

メンター

研修全体の統括は筆者になりますが、新卒メンバーがいつでも相談できるように1人につき1人のメンターを付けています。社会人経験が3年以上ある社員をメンターとしました。

最初の2週は毎日1on1を15分程度行ない、以降は毎週金曜日に1時間の1on1を実施。 また、メンター同士の交流として、2週に1度メンターの共有会を開き、相談や近況報告を行いました。

メンター制自体も初めての試みだったためメンター同士の対応内容や新卒全員の様子が共有される場作りは、実施してよかったです。

研修メニュー内容

各研修内容のご紹介です。

オリエンテーション

オリエンテーション

  • 外部ビジネス研修
  • コンプライアンス研修
  • セキュリティ研修
  • 開発環境の整備
  • 開発ツールの解説

がメインです。

Macを渡されて、「勝手に開発環境作ってね」というのは新卒エンジニアにはハードルが高いので、筆者が付きっきりで時間をかけてフォローしました。

オリエンテーションは約1週間程度ですが、ここで「メドレー社員の一人になった」という実感を持ってもらうことができました。

開発基礎研修

大きく2部構成です。最初の部では、メドレーでエンジニアに期待していることや、既存サービスなどのシステム構成・ビジネスの流れなどを座学で実施しました。

もう一つの部では書籍の輪読をしました。この輪読は、Webサービスの基本の仕組みと、Webサーバ自体を支えるOSであるLinuxの基本を覚えてもらいたいという趣旨で開催しました。

メドレーについて

こちらの部ではCTO平山から「メドレーのエンジニアとして求めること」と題して、求められるエンジニアリングとは何なのか?自分達のキャリアパスなどをディスカッションしました。

その後は、ジョブメドレーCLINICS介護のほんね などメドレーが提供しているプロダクトについて、システムの概要やビジネスモデルとシステムの対応について講義。

メドレーでのエンジニアは各々専門性がある技術領域を持ちつつ、その領域に限定せずに広い分野で開発をしていますし、プロダクトを第一に考え開発しますが、そのために技術を武器としていくバランス感覚が必要になります。

この段階でまずこうしたメドレーでエンジニアとして働くとはどういうことなのかという知識や考え方を新卒メンバーに勉強してもらいました。 エンジニアとは何か エンジニアの価値は何か プロエンジニアとは何か エンジニアではない職種との違いは何か といった基本的な話から、 2030年のみんなはどうなっているのか、どうなっていたいのか 先輩エンジニアはどのようなことに悩み、どのようにアプローチをして、力をつけてきたのか、それを超えるためのヒントはどこにあるか メドレーのエンジニアとして求めたいことは何か といった踏み込んだ話も含め、個人ワークやグループワークも交えながら伝えていきました。

導入があることで、これからのカリキュラムを実施していく上での心構えができる期間だったのではないかと思います。

輪読会

座学でプログラミングのことを勉強させるのではなく、主体性を持ち、基礎知識を習得してほしいと考えていたので、プランを作っている初期段階から輪読会をすることを決めていました。 参考にさせていただいたのはドワンゴさんの2016年の研修の記事です。

輪読で使用する本の選定は悩んだのですが、弊社で使っているRubyRuby on Railsのことや、JavaScriptなどの技術より、基本となるWeb自体についての知識や、Webサーバで使うLinuxの事などを習得してもらいたいということを考えて以下の2冊で輪読を行いました。

「Webを支える技術」の輪読の形式は毎回決まった章を筆者が講義しつつ、時折質問などをメンバーに投げかけたりしながら理解を深めました。

議事録も新卒メンバー全員で順番を決めてもらうという、自主性に基づくスタイルにしました。まず輪読の雰囲気になれてもらうこと、それから議事録を取りつつドキュメンテーションの練習をすることを狙いとしています。

最初はぎこちなかった部分もありましたが、回を重ねるにつれて、自分の経験や知識も含めたディスカッションにも発展するようになり、全員自主性を持ちながら実施できました。

対して「Goならわかるシステムプログラミング」については新卒メンバーに章を割り当てて、各自講師をしてもらいました。

元々レポートを3回発表することを予定していたので、本の内容を読んできちんと理解した上で、他人へ伝える力を養うことをサブ目標にしています。

さらなる自主性も必要になる上、本の性質上ほとんどのメンバーが触っていないGo言語を使ってプログラムを書いてシステムのことを理解しないといけない為、プログラムの本質的な部分に触れることもできたのではないかと思います。

開発実践

開発実践は上記の開発基礎と並行して午後から実施しました。 1日の午前が開発基礎、午後が開発実践というスケジュールです。

実践は新卒メンバーで社内ツールを実際の業務形式で開発してもらいました。

題材は「メドレーの使い方に合ったビルの予約システムを作る」というものです(以前SmartHRさんが同じビルだったので少しアプローチが違いますがブログに書いてました)。

メドレーでの業務開発と同じ形式で

  • ユーザーからの要望をヒアリング
  • 要件定義
  • 開発計画の策定
  • システム設計
  • チームで分担してながらの開発
  • ベータ版としてリリースしたものをブラッシュアップ
  • 実稼働するための環境整備をしながらリリースする

という一連のプロセスで開発しました。

「開発自体どうやって進めるか」「仕様をどうするか」など基本的な所から、全行程を新卒メンバー主体で考えて実行してもらい、メンター陣は所々MTGやPRをレビューしながら、アドバイスをするという形式で行いました。

新卒メンバー全員が同じスキルセットを持っているわけでもないですし、得意・不得意も違う為、まず最初に彼ら自身にリーダーを決めてもらい、リーダーがオーナーシップを持って開発を進めてもらいました。

チームでの開発というのはほとんど全員が初めてだったため、かなり困惑しているところもありましたが、研修の過程で理解した互いのスペシャリティを活かして、役割分担をしつつ、決まった納期にきちんとリリースすることができました。メンターとしてそばで見ていましたが、新卒メンバー全員の成長を実感しましたし、純粋に凄いと感じました。

途中で納期に間に合わせるための要件の取捨選択をしなければならなかったり、自分達が考えた仕様が必ずしもベストというわけではなく、さらに色々と考える要素が必要だったりという開発のリアルを経験できたのは次のOJTに活きたと思います。

余談ですが、こちらの元々のシステムを調査する上で「Webを支える技術」の知識が早速役に立つという場面が多く、やはり基本は大事だな、と思った次第です。

開発部OJT

基礎研修が終わってから、既存サービスにジョインしてのOJT実施となりました。

ここまでの研修で、ある程度の知識や業務の進め方などは習得していたので、何をすればよいか分からないということはありませんでした。

メンバーによってはここで時間を取ってRuby on Railsについて習得をしてもらいました。 大きい失敗なども特にはなく粛々と進められたのは良かったのではないかと思います。

事業部OJT

開発部OJTの途中で2週間ずつ時間を取って、人材プラットフォーム事業と医療メディア事業での事業部OJTを行いました。

どこで顧客とコンタクトし、お金をいただき、どのような形で自分達が作ったシステムに関わっていくのか?というのをこの時期に体験してもらうことが目的です。

研修はビジネスの流れに沿って行ないました。研修メニューは、事業部の主要メンバーにコンセプトの共有をし、メニューを考えて実施してもらいました。(ありがとうございます!)

実際に電話でアポイントを取ったり、顧客のサポートを電話やビデオチャットでしたり、営業をどうやっているのかを体験したり…などを2週間かけて新卒メンバーに体験してもらいました。

この後に実際「このシステムの機能はこういうときに使うのかと実感した」とか「やっていてこのような仕様のほうが良いと思った」などの感想をそれぞれのメンバーが持っていて、やはり実施して良かったなと強く感じました。

レポート発表

それぞれの研修の終わりにはレポート発表の時間を設け、一人一人振り返りを書いてもらいます。その為に週報の提出も義務付けました。また研修期間の終了時には弊社役員陣にプレゼンする最終レポート発表の時間を取りました。

ひたすら研修内容をこなしていくという形になりがちなので、振り返りの期間を設けて記録を付けていき、自分の成長や反省などを可視化したいという目的です。

また、メドレーではドキュメントドリブンで開発に限らず全社員がConfluenceでドキュメントを書いていく文化なので、文書を誰にでも分かるように論理的に書く技術が求められます。こういったレポートの記述やそのフィードバックから文書技術を高めてほしいという目的もありました。

レポートに関してはメンター陣やマネージャ陣に発表してもらうという形にしていたので、発表自体やレポートのまとめ方などに都度フィードバックをするようにしました。

最初はレポートが読みづらいなどもありましたが、回を重ねるごとに段々洗練されたレポートや発表になってきたのが印象的です。

最終レポートは代表を始めとした経営陣に向けてレポートを発表してもらいました。今まで自分達がやってきた全ての業務を、前提の知識がない聴衆に向けて発表するということで、各自が趣向を凝らしての発表になり、経営陣からも高評価をもらっていました。

まとめ

メドレーで初の新卒研修は以上のような形で終わることができました。

かなりのハードスケジュールだったとか、開発部OJTをもう少し現場と色々と話しあったほうが効果的だったかもなど反省点もありますが、現在新卒メンバーが10月から実際の業務で活躍しているところを見ているので、ある程度の成功を収めることができたのではないかと思います。

来年度のメニューはまた違ったものになる可能性がありますが、今年の研修でも重視した「メドレーでエンジニアとして働くことに対する意義を感じながら業務をしてもらう」という部分はズラさずに実施していければと思います。

長々とお付き合いいただきありがとうございました。

社内勉強会TechLunchで Badging API について発表しました

みなさん、こんにちは。開発本部のエンジニアの舘野です。先日、社内勉強会「TechLunch」で Badging API について発表したので、その内容を紹介させていただきます。

Badging API とは

Badging API とは、ネイティブアプリのアプリアイコン上に表示されるバッジと同様に、ウェブアプリのアイコン上にバッジを表示することができる Web API です。

 

ネイティブアプリで可能なこと全てをウェブアプリでも可能にすることを目指す、Fugu というプロジェクトで実現に向けて動いている API の1つで、Chrome 73 から Origin Trials として利用可能になっています。Origin Trials とは、試験的に特定の開発者に限定してAPIを利用できるようにする仕組みのことで、正式リリース前にAPIに対する有用なフィードバックを受け取ることができるものです。

 

このAPIの最新の概要や仕様については、 WICGGithubBadging APIのリポジトリを用意しているので、そこで確認することができます。

WICG(The Web Incubator Community Group)は、先進的なウェブ技術について検討するコミュニティグループで、W3Cのグループの1つです。

提案されている API のインターフェースは、現時点(2019/08/14)では以下のようになっています。

 

https://github.com/WICG/badging/blob/master/explainer.md#the-api

 

  • Badgewindowオブジェクトのメンバとして持つ
  • Badgeには2つのメソッドが存在する
    • Badge.set()
    • Badge.clear()
  • Badge.set(5)のようにset()に整数を渡してバッジ上に数字を表示する
  • 単にBadge.set()で呼び出すとフラグとしてバッジを表示する
  • Badge.set(5, { scope:  ‘/baz’ })のようにオプションを渡して特定のスコープ配下で表示されるように指定できる
    • オプションでスコープが指定されてない場合、スコープは/になる

ローカル環境で試す

 

実際にどのような形でバッジを表示できるかを確認するために、今回はローカル環境(macOS 10.14、Chrome76)で試してみました。

API自体は非常にシンプルなので、PWAのアプリを用意してインストールするだけで簡単に試すことができます。

インストールされていないウェブアプリでも、タブのfavicon上やブックマークアイコン上にバッジを表示することも議論されているようですが、今のところインストール済みのウェブアプリでしかバッジは表示されません。

 

最初にAPIを利用可能な状態にする必要がありますが、上述の通りAPI自体が現在Origin Trials の段階なので、Origin Trialsの利用申請を行うかローカル環境であればchrome://flagsで実験的な機能を有効にする(#enable-experimental-web-platform-features)かのいずれかを行う必要があります。

 f:id:medley_inc:20190827173844p:plain

今回はローカル環境で試すだけなので、chrome://flagsから enable-experimental-web-platform-features を有効にしておきます。

実験的な機能を利用可能にしたことでBadging API自体は利用可能になりますが、window.Badgeとして利用可能になっているのではなく、Origin Trials の段階ではBadgeではなくExperimentalBadgeとして提供されています。

 

次に、サンプルのプロジェクトを用意してwebpack-dev-serverでローカルサーバを用意します。

 

$ yarn init

$ yarn add --dev webpack webpack-cli webpack-dev-server html-webpack-plugin copy-webpack-plugin

 

webpack-dev-serverでローカルサーバが見れる状態になるようにwebpack.config.jsに設定を記述します。

const path = require('path')

const HtmlWwebpackPlugin = require('html-webpack-plugin')

 

module.exports = {

  mode: 'development',

  devServer: {

    https: true,

  },

  entry: {

    app: ['./src/js/app.js'],

  },

  output: {

    path: path.resolve(__dirname, './dist'),

  },

  plugins: [

    new HtmlWwebpackPlugin({

      template: 'src/index.html',

    }),

  ],

}

 

次にmanifest.jsonを用意します。manifest.jsonは、そのアプリがどういったものか、また、インストールした時にどのように振る舞うかをブラウザに伝えるための設定ファイルになります。

https://app-manifest.firebaseapp.com/ のようなサービスでmanifest.jsonとアイコンを各種サイズ自動生成できるので、今回はこのサービスで生成します。

 

{

  "name": "badging-api-playground",

  "short_name": "badge",

  "theme_color": "#5B5CFD",

  "background_color": "#5B5CFD",

  "display": "standalone",

  "orientation": "portrait",

  "prefer_related_applications": false,

  "Scope": "/",

  "start_url": "/",

  "icons": [

    {

      "src": "images/icons/icon-72x72.png",

      "sizes": "72x72",

      "type": "image/png"

    },

    {

      "src": "images/icons/icon-96x96.png",

      "sizes": "96x96",

      "type": "image/png"

    },

    {

      "src": "images/icons/icon-128x128.png",

      "sizes": "128x128",

      "type": "image/png"

    },

    {

      "src": "images/icons/icon-144x144.png",

      "sizes": "144x144",

      "type": "image/png"

    },

    ….

  ],

  "splash_pages": null

}

 

webpack.config.jsの方にmanifest.jsonをローカルサーバで配信されるように設定を追加しておきます。

 

const path = require('path')

const HtmlWwebpackPlugin = require('html-webpack-plugin')

+ const CopyPlugin = require('copy-webpack-plugin')

 

module.exports = {

  ….

  plugins: [

    ….

+     new CopyPlugin([

+       {

+         from: 'src/manifest.json',

+         to: '',

+       },

+       {

+         from: 'src/images/icons',

+         to: 'images/icons/'

+       },

+     ]),

  ],

}

 

ここまででChromeのApplicationタブからmanifest.jsonが認識されいてることが確認できますが、インストール可能な状態にはなっていません。

f:id:medley_inc:20190826185511p:plain

アプリをインストール可能な状態にするには いくつかの基準 があり、service workerが必要になります。今回はWorkbox のwebpackプラグインで対応します。

 

yarn add --dev workbox-webpack-plugin

workboxにはGenerateSWとinjectManifestの2つのモードがあり、今回はどちらでも問題ないかと思いますがinjectManifestモードを利用します。

 

const path = require('path')

const HtmlWwebpackPlugin = require('html-webpack-plugin')

const CopyPlugin = require('copy-webpack-plugin')

+ const { InjectManifest } = require('workbox-webpack-plugin')

 

module.exports = {

  ….

  plugins: [

    ….

+     new InjectManifest({

 

+       swSrc: path.resolve(__dirname, 'src/sw.js'),

+     }),

  ],

}

 

app.jsの方でservice workerの登録がされるように記述しておきます。

if ('serviceWorker' in navigator) {

  window.addEventListener('load', () => {

    navigator.serviceWorker.register('./sw.js').then((res) => {

      console.log(res)

    }).catch((err) => {

      console.error(err)

    })

  })

}

 

service workerの対応が済むとインストール可能なアプリの基準を満たすので、Chrome76ではアドレスバーにオムニボックスが表示され、そこからインストールが可能になっています。

f:id:medley_inc:20190826185538p:plain

f:id:medley_inc:20190826185554p:plain

インストールするとLaunchpadにアプリアイコンが表示されたので、実際にBadge APIを試してみます。

window.ExperimentalBadge.set()を呼び出すと、フラグとしてバッジがつきます。

f:id:medley_inc:20190826185622p:plain

window.ExperimentalBadge.set(1)のように引数に数値を入れて呼び出すと、バッジは数字が入った状態で表示されます。

f:id:medley_inc:20190826185641p:plain

window.ExperimentalBadge.clear()でバッジがクリアされ、元のアプリアイコンだけの状態に戻ります。

f:id:medley_inc:20190826185653p:plain

非常に簡単ではありますが、このようにしてウェブアプリのアイコンにバッジをつけられることが確認できました。

なお、このサンプルプロジェクトは https://github.com/makotot/badging-api-playground にあげてあります。

 

まとめ

近い将来正式リリースされる可能性が高いAPIを試すことで、今後ウェブアプリでどのようなことが実現可能になっていくかの一端を垣間見ることができました。

 

API自体がOrigin Trialの段階で、ブラウザのタブのfavicon上やブックマークアイコン上に表示したいケースであったり、バッジはどこまでの範囲で適用するべきかのスコープの問題であったり、最終的にどのような形に仕様が整理されるかまだ明確ではない部分もあります。

 

最終的にどのように課題が解決されていくか注目したいと思います。